[C][Leetcode]剑指offerⅡ 026.重排链表

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

 L0 → L1 → … → Ln-1 → Ln 


请将其重新排列后变为:

L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → …

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

输入: head = [1,2,3,4]
输出: [1,4,2,3]

提示:

  • 链表的长度范围为 [1, 5 * 104]
  • 1 <= node.val <= 1000

【思路】

1,由题目要求,第n个结点插到第一个结点后,第n-1个结点插入第2个结点后...,可见重排后的链表末端是原先的最中间的结点。可将链表后半段(代码中后半段指针为L2)逆置后逐个插入前半段(L1)

2,链表无法随机存取,其逆置应当找到链表中间的结点和最后的结点,对后半段的每个结点,依次插入到最末尾结点的后面(头插法建立逆序链表)。具体实现使用快慢指针,且为了保证end指针最后不为空,我们让它每次只后移一位,且它独自后移了一次后,慢指针和快指针同时后移一次。使用move记录慢指针当前是否可以移动。

具体实现:若move=0,即不是慢指针移动的轮次,快指针end先后移一次,令记录变量move=1。然后由于move=1,慢指针middle与快指针end同时后移,再令move=0,直到end下一位为空,此时end指向最后一个结点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


void reorderList(struct ListNode* head){

    struct ListNode* end;
    struct ListNode* middle;//用于找中间结点和末尾结点的快慢指针

    struct ListNode* l1;
    struct ListNode* l2;//用于最后一步合并前后半段的两个指针

    struct ListNode* p;//交换节点时用的临时指针
    struct ListNode* end2;

    int move=0;

    end=head;
    middle=head;
    if(!head->next) return;

    while(end->next){
        if(move==0) {
            end=end->next;
            move=1;
        }else{
            middle=middle->next;
            end=end->next;
            move=0;
        }
    }//while 找到L[n/2]

    l2=middle->next;
    middle->next=NULL;//一定要把后半段彻底【摘下来】,敲代码时缺了这步导致进入死循环。。。
    end->next=NULL;

    while(l2!=end){
        p=l2;
        l2=l2->next;
        p->next=end->next;
        end->next=p;

    }//while 逆置后半截
  
   // middle->next=l2; //测试逆置代码段是否有问题的语句

    l1=head;
    
    while(l2){
        p=l2;
        l2=l2->next;
        
        p->next=l1->next;
        l1->next=p;
        l1=p->next;
        
        
    }//while 将逆置过的后半截链表l2插入l1
 
}

思路不是很难想(只要知道逆置链表这个操作),代码也不是多复杂,但是没有将middle的next置为空导致超时,还排查了好久。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值