143. Reorder List

本文详细解析了链表重排序算法的两种实现方法,包括使用快慢指针找到链表中点并断开反转后半段,以及利用栈来辅助完成重排序。通过具体示例展示了如何将链表L0→L1→...→Ln-1→Ln重新排列为L0→Ln→L1→Ln-1→L2→Ln-2→...,并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…

You may not modify the values in the list’s nodes, only nodes itself may be changed.

Example 1:

Given 1->2->3->4, reorder it to 1->4->2->3.

Example 2:

Given 1->2->3->4->5, reorder it to 1->5->2->4->3.

grandyang: http://www.cnblogs.com/grandyang/p/4254860.html

方法1:

思路:用快慢指针找到链表中点,断开并反转后半段。将两个链表间隔融合。

易错点:

  1. fast/slow 的方法从prev起找到的是左中卫,从head起找到的是右中卫。一般来说左中卫比较有用。
  2. if (!head || !head->next || !head->next->next) return:虽然没什么必要,但是避免思考超级edge的case。比如只有一个数。
//  null     1    ->  2   ->   3   ->   4   ->   5 
//  prev             slow     mid     fast        
//  null     1    ->  2       3   ->   4   ->   5 
//  prev             slow    last    next       
//           1    ->  2   null <-   3    4 -> 5
//                         prev   last  next
//           1    ->  2   null <-   3    4 -> 5
//                                prev last  next
//           1    ->  2   null <-   3 <- 4    5
//                                      prev last  next
//           1    ->  2   null <-   3 <- 4 <- 5
//         head                              prev last 
//          1    ->   2
//         head      next
//          5    ->   4    ->   3
//         prev     



class Solution {
public:
    void reorderList(ListNode *head) {
        if (!head || !head->next || !head->next->next) return;
        ListNode *fast = head, *slow = head;
        while (fast->next && fast->next->next) {
            slow = slow->next;
            fast = fast->next->next;
        }
        ListNode *mid = slow->next;
        cout << mid -> val ;
        slow->next = NULL;
        ListNode *last = mid, *pre = NULL;
        while (last) {
            ListNode *next = last->next;
            last->next = pre;
            pre = last;
            last = next;
        }
        while (head && pre) {
            ListNode *next = head->next;
            head->next = pre;
            pre = pre->next;
            head->next->next = next;
            head = next;
        }
    }
};
class Solution {
public:
    void reorderList(ListNode *head) {
        ListNode* newHead1 = new ListNode(-1), * slow = newHead1, * fast = newHead1;
        newHead1 -> next = head;
        while (fast && fast -> next) {
            slow = slow -> next;
            fast = fast -> next;
            fast = fast -> next;
        }
        // cut the link between prev and slow
        ListNode* newHead2 = slow -> next;
        slow -> next = nullptr;
        // reverse newHead2
        ListNode* prev = nullptr, * cur = newHead2;
        while (cur) {
            ListNode* tmp = cur -> next;
            cur -> next = prev;
            prev = cur;
            cur = tmp;
        }
        // merge two list
        newHead2 = prev;
        // newhead2存在,head一定存在,其实不用查head。
        while (head && newHead2) {
            ListNode* tmp = head -> next;
            head -> next = newHead2;
            newHead2 = newHead2 -> next;
            head -> next -> next = tmp;   
            head = tmp;
        }
        return;
    }
};

方法2: stack

易错点:

最后断开栈顶,否则会闭环

class Solution {
public:
    void reorderList(ListNode *head) {
        if (!head || !head->next || !head->next->next) return;
        stack<ListNode*> st;
        ListNode *cur = head;
        while (cur) {
            st.push(cur);
            cur = cur->next;
        }
        int cnt = ((int)st.size() - 1) / 2;
        cur = head;
        while (cnt-- > 0) {
            auto t = st.top(); st.pop();
            ListNode *next = cur->next;
            cur->next = t;
            t->next = next;
            cur = next;
        }
        st.top()->next = NULL;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值