430 扁平化多级双向链表
思路
1. 题目:Node 需处理 prev next child
2. 大体:遍历链表;判断节点是否有child节点;
有,存储temp->next,令ch = temp->child,处理当前节点temp->child指向nullptr,temp->next = ch,ch->prev = temp,
然后再遍历子链表新建指针childTail指向其中最后一个节点,
然后处理temp原next next->prev = childTail,childTail->next = next;【思路√但代码原逻辑混乱】
3. 细节:因增插节点,所以dummy;new_head->prev =nullptr;
/*
// Definition for a Node.
class Node {
public:
int val;
Node* prev;
Node* next;
Node* child;
};
*/
class Solution {
public:
Node* flatten(Node* head) {
//双链表,增加节点,虚拟头部
Node* dummy = new Node(0);
dummy->next = head;
Node* temp = dummy;
while(temp){
if(temp->child){
Node* ch = temp->child;
Node* next = temp->next;
temp->next = ch;
ch->prev = temp;
temp->child = nullptr;
//需要新建
Node* chTail = ch;
while(chTail->next){//ch指向最后一个结点
chTail = chTail->next;
}
if(next){
chTail->next = next;
next->prev =chTail;
}
}
temp = temp->next;
}
Node* new_head = dummy->next;
if (new_head) {
new_head->prev = nullptr; // 将新头节点的prev设置为null
}
delete dummy;
return new_head;
}
};
61 旋转链表
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
思路
1. 题目:右移k个位置
2. 大体:(k>len)确定真实移动节点数,判定head的长度,计算k = k % len;将头尾相接;判定新尾部,newTail = head,循环len-k-1次,将尾部断开,并保存新的头部newHead = newtail->next;【思路√但代码原逻辑混乱】
3. 细节:k % len == 0 或者 k == 0 或者head为空
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(!head || k == 0 ) return head;
//链表长度
ListNode* cur = head;
int len = 1;
while(cur->next){
cur = cur->next;
len++;
}
//实际移动步数
k = k % len;
if(k == 0){return head;}
//循环链表,头尾相接
cur->next = head;
//找到新尾部
int n = len - k;
ListNode* newTail = head;
for(int i = 1 ; i < n ; i++){
newTail = newTail->next;
}
//断开循环
ListNode* newHead = newTail->next;
newTail->next = nullptr;
return newHead;
}
};
24 两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
思路
1. 题目:两两交换 节点
2. 大体:遍历链表;保存指针的next和nextnext,进行节点交换;移动指针至新交换的第二个节点即原next上,继续循环。【思路√代码细节还是有问题】
3. 细节:while循环保证next和nextnext都存在,当head的长度为0or1即if(!head || !head->next)return head;因增删改节点,所以dummy。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(!head || !head->next)return head;
ListNode* dum = new ListNode(0);
dum->next = head;
ListNode* cur = dum;
while(cur){
ListNode* N = cur->next;
ListNode* newN = N->next;
if(newN){
cur->next = newN;//更新尾部
N->next = newN->next;
newN->next = N;
cur = N;
}else{
break;
}
}
ListNode* newHead = dum->next;
delete dum;
return newHead;
}
};
修改:可以将条件语句融到while循环的判断中
Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(!head || !head->next) return head;
ListNode* dum = new ListNode(0);
dum->next = head;
ListNode* cur = dum;
while(cur->next && cur->next->next){
ListNode* first = cur->next;
ListNode* second = cur->next->next;
//交换节点
first->next = second->next;
cur->next = second;
second->next = first;
//移动指针
cur = first;
}
ListNode* newHead = dum->next;
delete dum;
return newHead;
}
};
92 反转链表Ⅱ
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
思路
1. 题目:left <= right;反转从位置 left 到位置 right 的链表节点
2. 大体:移动到要反转节点的前一个;翻转;链接已翻转部分p和未反转部分cur【出错部分,只链接p没有链接cur】。
3. 细节:left == right || !head return head;对head的第一个节点会影响,dummy
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
if(left==right || !head->next)return head;
ListNode* dum =new ListNode(0);
dum->next = head;
ListNode* prev = dum;
//移动到边界处,prev用于保存颠倒部分前的内容
for(int i = 1 ; i < left ; i++){
prev = prev->next;
}
//颠倒链表
ListNode* p = nullptr;
ListNode* latt = nullptr;
ListNode* cur = prev->next;
for(int i = left ; i <=right;i++){
latt = cur->next;
cur->next = p;
p = cur;
cur = latt;
}
//cur为为反转的部分 p为翻转的部分
prev->next->next = cur;
prev->next = p;
ListNode* newHead = dum->next;
delete dum;
return newHead;
}
};