LeetCode刷题笔记 143. 重排链表

143. 重排链表

题目要求

143. 重排链表

题解

https://github.com/soulmachine/leetcode

找到中间节点,断开,把后半截单链表 reverse 一下,再合并两个单链表。

class Solution {
public:
    ListNode* reverse(ListNode *head){
        if(!head||!head->next) return head;

        ListNode *prev=head;
        for(ListNode *cur=head->next,*next=cur->next;cur;
        prev=cur,cur=next,next=next?next->next:nullptr){
            cur->next=prev;
        }
        head->next=nullptr;
        return prev;
    }
    void reorderList(ListNode* head) {
        if(!head||!head->next) return;

        ListNode *fast=head,*slow=head,*prev=nullptr;
        while(fast&&fast->next){
            prev=slow;
            slow=slow->next;
            fast=fast->next->next;
        }
        prev->next=nullptr;  //从中切开

        slow=reverse(slow);

        //合并
        ListNode *cur=head;
        while(cur->next){
            ListNode *tmp=cur->next;
            cur->next=slow;
            slow=slow->next;
            cur->next->next=tmp;
            cur=tmp;
        }
        cur->next=slow;
    }
};

原谅我太菜,后边while循环里发生的情况单凭脑子真的想不来,所以,再次祭出playground。
看下这部分:

        ListNode *cur=head;
        while(cur->next){
            ListNode *tmp=cur->next;
            cur->next=slow;  // @1
            slow=slow->next;  
            cur->next->next=tmp;  // @2
            cur=tmp;  // @3
        }
        cur->next=slow;  // @4
ListNode *cur=head;
while(cur->next){
            ListNode *tmp=cur->next;
            cur->next=slow;  // @1
            out = listNodeToString(head);
            cout << "@1 "<<out << endl;
            slow=slow->next;
            cur->next->next=tmp; // @2
            out = listNodeToString(head);
            cout << "@2 "<<out << endl;
            cur=tmp; //@3
            out = listNodeToString(head);
            cout << "@3 "<<out << endl;
        }
        cur->next=slow;  //@4
        out = listNodeToString(head);
        cout << "@4 "<<out << endl;
HeadBeforeReverse [1, 2, 3]
SlowBeforeReverse [4, 5, 6, 7]
SlowAfterReverse [7, 6, 5, 4]
@1 [1, 7, 6, 5, 4]
@2 [1, 7, 2, 3]
@3 [1, 7, 2, 3]
@1 [1, 7, 2, 6, 5, 4]
@2 [1, 7, 2, 6, 3]
@3 [1, 7, 2, 6, 3]
@4 [1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]

不偷懒了,总结一下

  1. ListNode *cur=head;cur指向表头,如本例的1
  2. ListNode *tmp=cur->next;tmp保存本轮要移后的节点(cur的下一个节点),如本例[1,2,3],
    cur:1 tmp:2 本轮结束时相对位置应为[1,7,2],中间插入了另一半链表中slow指向的节点。
  3. cur->next=slow;当前cur指向另一半链表slow指向的节点,如[1,2,3]->[1, 7, 6, 5, 4]
  4. slow=slow->next; slow指针后移,如[7,6,5,4]中slow由7到6
  5. cur->next->next=tmp; 把之前保存的节点插到cur后两步的位置,如将2插入[1, 7, 6, 5, 4]得
    [1, 7, 2, 3],注意此时会把前半部分的剩余部分也带上。
  6. cur=tmp;将cur指针移到保存的节点的位置,如[1, 7, 2, 3]中,由1移动到2
  7. 重复2~6直到cur移出前半部分,如[1,2,3]
  8. 跳出循环后 cur->next=slow;无论链表为奇或偶,只需将后半链表剩余部分拼接到cur后面,后半部分最后会剩下一个或两个元素,如果是两个也无需担心,因为这个元素无论被分在哪个部分都只会在最后面,不影响最终结果。
发布了18 篇原创文章 · 获赞 0 · 访问量 1797

猜你喜欢

转载自blog.csdn.net/g534441921/article/details/104159008