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



/**

 *  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));
}









你可能感兴趣的:(C实现 LeetCode->Reorder List (双指针大法)(单链表是否有环))