206.反转链表
迭代写法
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* cur=head,*pre=nullptr;
while(cur!=nullptr){
ListNode* tmp=cur->next;//记录后一个节点
cur->next=pre;//改变指针
pre=cur;//pre、cur分别右移
cur=tmp;
}
return pre;
}
};
递归写法
class Solution {
public:
ListNode* reverse(ListNode* pre, ListNode* cur){
if(cur==nullptr){
return pre;
}
ListNode* tmp=cur->next;
cur->next=pre;
return reverse(cur,tmp);
}
ListNode* reverseList(ListNode* head) {
return reverse(nullptr,head);
}
};
92.反转链表 ||
先分割出 [ l e f t , r i g h t ] [left, right] [left,right] 区间的子链表,再调用上面反转链表的函数
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* cur=head,*pre=nullptr;
while(cur!=nullptr){
ListNode* tmp=cur->next;//记录后一个节点
cur->next=pre;//改变指针
pre=cur;//pre、cur分别右移
cur=tmp;
}
return pre;
}
ListNode* reverseBetween(ListNode* head, int left, int right) {
if (left >= right) {
return head;
}
ListNode* dummyHead=new ListNode(-1);
dummyHead->next=head;
ListNode* pre=dummyHead;
for(int i=0;i<left-1;i++){
pre=pre->next;
}
// leftNode、rightNode分别记录子链表的头节点和尾节点
ListNode* leftNode=pre->next;
ListNode* rightNode=leftNode;
for(int i=0;i<right-left;i++){
rightNode=rightNode->next;
}
ListNode* post=rightNode->next;
//切割出子链表
pre->next=nullptr;
rightNode->next=nullptr;
reverseList(leftNode);
//接回子链表
pre->next=rightNode;
leftNode->next=post;
return dummyHead->next;
}
};
穿针引线法
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
if(left>=right){
return head;
}
ListNode *dummyHead=new ListNode(-1);
dummyHead->next=head;
ListNode *pre=dummyHead;
//pre移动到节点left的前一个节点
for(int i=0;i<left-1;i++){
pre=pre->next;
}
ListNode *cur=pre->next;
// 第1次迭代反转2个节点,第2次迭代反转3个节点,依此类推
for(int i=0;i<right-left;i++){
ListNode* tmp=cur->next;
cur->next=tmp->next;
tmp->next=pre->next;
pre->next=tmp;
}
return dummyHead->next;
}
};
25.K个一组反转链表
迭代写法,套用上面的穿针引线法
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* dummyHead=new ListNode(-1);
dummyHead->next=head;
ListNode* pre=dummyHead;
ListNode* countNode=pre; //用来计数
// 先计数判断余下节点够不够k个,然后再确定是否反转,最后更新节点变量
while(true){
// 计算节点数
int count=0;
while(countNode->next!=nullptr && count<k){ //写成countNode!=nullptr会把空指针计算在内
countNode=countNode->next;
count++;
}
if(count<k){
break;
}
ListNode* preNext=pre->next;//记录pre下一次的位置, pre下一次的起点其实就是现在的pre->next
ListNode* cur=pre->next;
for(int i=0;i<k-1;i++){ //穿针引线法,第1次迭代反转2个节点,第2次迭代反转3个节点,依此类推
ListNode* tmp=cur->next;
cur->next=tmp->next;
tmp->next=pre->next;
pre->next=tmp;
}
// 更新节点变量
pre=preNext;
countNode=pre;
}
return dummyHead->next;
}
};
递归写法
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
//计数
ListNode* countNode=head;
int count=0;
while(countNode!=nullptr && count<k){ // 这里没有用dummyHead,因此判断条件为countNode!=nullptr,与迭代的写法有所区别
countNode=countNode->next;
count++;
}
if(count<k){
return head;
}
// 递归反转k个节点
ListNode* pre=head;
ListNode* cur=pre->next;
for(int i=0;i<k-1;i++){//这里和206.反转链表一样
ListNode* tmp=cur->next;
cur->next=pre;
pre=cur;
cur=tmp;
}
head->next=reverseKGroup(cur,k); //此时cur和countNode重合,cur是k个节点中的第一个
return pre; //pre是k个节点中的最后一个
}
};
24.两两交换链表中的节点
这题是K个一组反转链表的一个特例,令k=2
就能解决