您的位置:首页 > 其它

C实现 LeetCode->Reorder List (双指针大法)(单链表是否有环)

2015-06-22 18:30 453 查看
/**
 *  Given a singly linked list L: L0→L1→…→Ln-1→Ln,
 reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
 You must do this in-place without altering the nodes' values.
 
 
 
 For example,
 Given {1,2,3,4}, reorder it to {1,4,2,3}.
 
 
 分为四步。
 
 第一步找到链表长度。
 
 第二步把链表从中间分为两个子链表。
 
 第三步反转第二个子链表(ReverseLinkedList中的Reverse函数)。
 
 第四步把第二个子链表Merge到第一个子链表里面。
 */



//
//  ReorderList.c
//  Algorithms
//
//  Created by TTc on 15/6/22.
//  Copyright (c) 2015年 TTc. All rights reserved.
//
/**
*  Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes' values.

For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.

分为四步。

第一步找到链表长度。

第二步把链表从中间分为两个子链表。

第三步反转第二个子链表(ReverseLinkedList 中的Reverse函数)。

第四步把第二个子链表Merge到第一个子链表里面。
*/
#include "ReorderList.h"
#include <stdbool.h>
#include <stdlib.h>
#include "List.h"

/********************************************************************/
// LeetCode
/********************************************************************/

struct ListNode {
int val;
struct ListNode *next;
};

//双指针大法  链表反转函数(请背熟练)
/*Since only constant memory is allowed, time cost is O(k) */
static struct ListNode*
Reverse(struct ListNode *begin, struct ListNode *end){
struct ListNode* prev = begin->next;
struct ListNode* curr = prev->next;

while(curr != end){
prev->next = curr->next;
curr->next = begin->next;
begin->next = curr;
curr = prev->next;
}
return prev;
}

void
reorderList(struct ListNode* head) {
if (head == NULL)  return;

//Step1:  第一步找到链表长度。
struct ListNode *tmp = head;
int len = 0;
while (tmp != NULL) {
tmp = tmp->next;
++len;
}
int num_insertion = (len-1)/2;

//Step2:   第二步把链表从中间分为两个子链表。
tmp = head;
int count = 0;
while (count < len-1-num_insertion) {
tmp = tmp->next;
++count;
}
struct ListNode *second_half = tmp->next;
tmp->next= NULL;

//Step3:    第三步反转第二个子链表(ReverseLinkedList 中的Reverse函数)。
if (second_half != NULL && second_half->next != NULL) {
struct ListNode *dummyHead = (struct ListNode *)malloc(sizeof(*dummyHead));
dummyHead->next = second_half;
Reverse(dummyHead, NULL);
second_half = dummyHead->next;
}

//Step4:    第四步把第二个子链表Merge到第一个子链表里面。(隔槽插入)
struct ListNode *first_half = head;
while (second_half != NULL) {
struct ListNode *temp1 = second_half->next;
second_half->next = first_half->next;
first_half->next = second_half;
second_half = temp1;
first_half = first_half->next->next;
}
}

/********************************************************************/
/********************************************************************/

/********************************************************************/
// List.c 是范性类 单链表
/********************************************************************/
//反转单链表中  begin  到 end 节点 (如果是反转整个 单链表 则需要传 0,list_size(),需要创建一个虚拟头节点)
static ListElmt*
tt_Reverse(ListElmt *begin, ListElmt *end){

ListElmt* prev = begin->next;
ListElmt* curr = prev->next;

while(curr != end){
prev->next = curr->next;
curr->next = begin->next;
begin->next = curr;
curr = prev->next;
}
return prev;
}

void
tt_reorderList(ListElmt* head) {
if (head == NULL)  return;

//Step1:  第一步找到链表长度。
ListElmt *tmp = head;
int len = 0;
while (tmp != NULL) {
tmp = tmp->next;
++len;
}
int num_insertion = (len-1)/2;

//Step2:   第二步把链表从中间分为两个子链表。
tmp = head;
int count = 0;
while (count < len-1-num_insertion) {
tmp = tmp->next;
++count;
}
ListElmt *second_half = tmp->next;
tmp->next= NULL;
printf("second_half======>%d\n", *(int *)second_half->data);
print_listNode(second_half);

//Step3:    第三步反转第二个子链表(ReverseLinkedList 中的Reverse函数)。
if (second_half != NULL && second_half->next != NULL) {
ListElmt *dummyHead = (ListElmt *)malloc(sizeof(*dummyHead));
dummyHead->next = second_half;
ListElmt * result = tt_Reverse(dummyHead, NULL);
printf("result======>%d\n", *(int *)result->data);

second_half = dummyHead->next;
print_listNode(second_half);

}

//Step4:    第四步把第二个子链表Merge到第一个子链表里面。(隔槽插入)
ListElmt *first_half = head;
while (second_half != NULL) {
ListElmt *temp1 = second_half->next;
second_half->next = first_half->next;
first_half->next = second_half;
second_half = temp1;
first_half = first_half->next->next;
}
}

void
test_tt_reorderList(){
List l1;
list_init(&l1, free);
int *data ;
int array[15] = {10,9,8,7,6,5,4,3,2,1};
//    for (int i = 0; i< 10; i++) {
for (int i = 0; i< 10; i++) {
if ((data = (int *)malloc(sizeof(int))) == NULL)
return ;
*data = array[i];
if (list_ins_next(&l1, NULL, data) != 0)  //逐个插入元素
return;
}
print_list(&l1);
tt_reorderList(list_head(&l1));
printf("反转后*****************\n");
print_listNode(list_head(&l1));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: