入门级题解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]
示例二:
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;
}
}
};
我的垃圾代码
/**
* 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;
}
};
标签:head,ListNode,143,题解,nullptr,next,链表,节点,cur 来源: https://blog.csdn.net/m0_46663240/article/details/122597464