leetcode 143. 重排链表

48 阅读1分钟

实际上这题是由反转链表、合并链表、找到链表的中间节点一起组成,值得深思的是

- 链表节点为偶数

1 2 3 4 5 6(有两个中间节点,根据876. 链表的中间结点,我们找到的是第二个中间节点,即4)
分割为两部分后为:
1 2 3 4 | 5 6
后部分反转后:
1 2 3 4 | 6 5
合并结果为
1 6 2 5 3 4
与123 | 654
1 6 2 5 3 4结果一样!!!,所以不需要将链表(偶数个节点)划分为完全相等的两部分

- 链表节点为奇数

12345 123 54 结果很容易分析出来,就不过多讨论了

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverse(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* next = nullptr;
        ListNode* curr = head;
        while(curr) {
            next = curr->next;
            curr->next = prev;
            prev = curr;
            // 这个误写了,导致一直无法ac
            // curr = curr->next error!!!
            curr = next;
        }
        return prev;
    }

    ListNode* middle(ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while(fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
        }
        return slow;
    }

    ListNode* merge(ListNode* l1, ListNode* l2) {
        ListNode* dummy = new ListNode();
        ListNode* curr = dummy;
        while(l1 && l2) {
            curr->next = l1;
            l1 = l1->next;
            curr = curr->next;

            curr->next = l2;
            l2 = l2->next;
            curr = curr->next;
        }
        if(l1) {
            curr->next = l1;
        }
        if(l2) {
            curr->next = l2;
        }
        return dummy->next;
    }

    void reorderList(ListNode* head) {
        ListNode* mid = middle(head);
        ListNode* next = mid->next;
        mid->next = nullptr;
        ListNode* l2 = reverse(next);
        merge(head, l2);
    }
};