入门级题解143. 重排链表

写在前面:
链表的题
1.取独立节点,保存接口,接口即->next
2.会用哑节点,return dummy->next
3.最重要的是->next,理解,理解再理解,并随时能够掌握它的最新变化。

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

L0 → L1 → … → Ln - 1 → Ln 请将其重新排列后变为:

L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

输入:head = [1,2,3,4] 输出:[1,4,2,3]
入门级题解143. 重排链表
示例二:入门级题解143. 重排链表

https://leetcode-cn.com/problems/reorder-list/

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/reorder-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

读题及思路
感觉先把链表从中间一分为二,再把后半部分反转,再插入。。。

思路没问题,就是怎么实现
1.找中点:快慢指针,大概是同时出发,fast = 2*slow,fast遍历完成时,slow所在就是中点。
1 2 3 4 5
s 1 2 3
f 1 3 5
2.反转链表:核心思想就是让后面的的节点指向前一个,只不过在改变指向前1.要将前一个节点的next保存下来,2是要在保存好后指向null,得到独立的节点。
3.这个合并:
1 2 3 4 5 p
10 9 8 7 6 q
p->next = q
cur = q->next;
q = q->next;
q->next = p->next
q = cur
1 10 2 3 4 5 p
p = p->next->next;
思路总结
1.分割这,不用返回两段链表,返回中心节点,后一段就是中心节点,前一段就是中心节点->next = nullptr。
2.反转是取出独立节点,后一个指向它,并保存它的->next
3.合并想清楚也简单:
两段链表的next都得保存,且要在取出独立节点前保存,然后就是->next指向的变更即可。

模范代码

class Solution {
public:
    void reorderList(ListNode* head) {
        if (head == nullptr || head->next == nullptr) return;
        ListNode* mid = FindMiddleNode(head);   // 找到中间节点
        ListNode* l1 = head;
        ListNode* l2 = mid->next;
        mid->next = nullptr;
        l2 = ReverseList(l2);   // 反转后半段的链表节点
        mergeList(l1, l2);      // 合并两端长度相差不超过1的链表
    }

    // 快慢指针找到中间节点
    ListNode* FindMiddleNode(ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast->next != nullptr && fast->next->next != nullptr) {
            slow = slow->next;
            fast = fast->next->next;
        }
        return slow;
    }

    // 反转链表
    ListNode* ReverseList(ListNode* head) {
        ListNode* pre = nullptr;
        ListNode* cur = head;
        ListNode* next;
        while (cur != nullptr) {
            next = cur->next;
            cur->next = pre; // 反转
            pre = cur;       // 向后移动
            cur = next;
        }
        return pre;
    }

    // 合并链表
    void mergeList(ListNode* l1, ListNode* l2) {
        ListNode* temp1;
        ListNode* temp2;
        while (l1 != nullptr && l2 != nullptr) {
            temp1 = l1->next;
            temp2 = l2->next;
            
            l1->next = l2;
            l1 = temp1;

            l2->next = l1;
            l2 = temp2;
        }
    }
};

我的垃圾代码
入门级题解143. 重排链表

/**
 * 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:
    void reorderList(ListNode* head) {
        ListNode* sHead = findMidNode(head);
        ListNode* right = sHead->next;
        sHead->next = nullptr;
        ListNode* left = head;
        ListNode* newright = reverseList(right);
        head = addList(left,newright);
    }
//找到中间的节点
    ListNode* findMidNode(ListNode* head){
        ListNode* slow = head; 
        ListNode* fast = head;
        while(fast->next&&fast->next->next){
            slow= slow->next;
            fast = fast->next->next;
        }
        return slow;
    }
//反转
    ListNode* reverseList(ListNode* head) {
        ListNode* p = head;
        ListNode* cur = nullptr;
        while(p){
            ListNode* next = p->next;
            p->next = cur;
            cur = p;
            p = next;
        }
        return cur;
    }
//归并
    ListNode* addList(ListNode* left,ListNode* right) {
        ListNode* l = left;
        ListNode* r = right;
        ListNode* cur1 = nullptr;
        ListNode* cur = nullptr;
        while(l&&r){
           cur = r->next;//保存r->next
           r->next = nullptr;//独立节点
           cur1 = l->next;//保存l的接口
           l->next = r;
           l = l->next;
           l->next = cur1;
           l = l->next;
           r = cur;
        }
        return left;
    }
};
上一篇:promise学习---promise的API


下一篇:即兴表达