题型
反转整个链表
反转链表前N个节点
链表内指定区间反转
K个节点一组反转链表
反转整个链表
思路1:
迭代,定义三个辅助链表节点指针pre、cur、nxt,pre为遍历链表时所在节点cur的前驱节点,nxt为cur的后驱节点。
步骤:
1.nxt指向cur下一个节点;
2. cur的下一个节点修改为pre;
3. pre指向当前节点cur;
4. cur指向nxt;
代码:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode* pre=nullptr;
ListNode* cur=pHead;
ListNode* nxt=pHead;
while(cur){
nxt=cur->next;
cur->next =pre;
pre =cur;;
cur =nxt;
}
return pre;
}
};
思路2:
递归,定义一个函数,参数为链表头节点,返回值为反转链表的头节点。
步骤:
1.确定base case,head为空或者head的下一个节点为空,反转链表头节点为其本身,则返回head;
2.反转以head的下一个节点为头节点的链表,并返回新链表头节点
3. 设置head的后驱节点的下一个节点为head;
4. head下一个节点改为nullptr,即链表尾节点;
5. 返回新链表头节点;
代码:
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead==nullptr || pHead->next==nullptr) return pHead;
ListNode* head =ReverseList(pHead->next);
pHead->next->next =pHead;
pHead->next=nullptr;
return head;
}
};
反转链表前N个节点
思路:迭代or递归
迭代:反转整个链表相当于反转[头节点,nullptr],左闭右开,结束条件为cur==nullptr(右端点),那么反转前n个节点,需先找到第n+1个节点,将结束条件改为对应的节点即可。
递归:定义一个函数,参数为(head,n),返回反转前n个节点后的头节点。当n为1时,结果为其本身。先完成head节点后驱节点的前n-1个节点的反转,记录新头节点的后驱节点,将head后驱节点的下一个节点设置为head,head的下一个节点设置为新头节点的后驱节点,返回新头节点。
递归代码:
ListNode* reverseN(ListNode* head,int n){
if(n==1){
return head;
}
ListNode* last= reverseN(head->next, n-1);
ListNode* post=head->next->next;
head->next->next=head;
head->next =post;
return last;
}
链表内指定区间反转
思路:迭代 or递归
迭代:将链表的m位置到n位置之间的区间反转,找到m位置和n+1位置,然后使用反转链表的迭代方法即可。
递归:定义一个函数,参数为(head,m, n),返回链表的m位置到n位置之间的区间反转后的头节点。
1.base case,当m=1,即反转前n个节点,调用上文reverseN(head,n)即可。
2.当head向后一个节点移动,相当于要反转链表的[m-1,fn-1]区间,
3.将head下一个节点指向以head->next为头反转后的头节点,返回head;
递归代码:
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
if(m==1) {
ListNode* l =reverseN(head,n);
return l;
}
head->next = reverseBetween(head->next,m-1,n-1);
return head;
}
ListNode* reverseN(ListNode* head,int n){
if(n==1){
return head;
}
ListNode* last= reverseN(head->next, n-1);
ListNode* post=head->next->next;
head->next->next=head;
head->next =post;
return last;
}
};
K个节点一组反转链表
思路:迭代or反转
迭代:[1:k+1],[k+1:2k+1]....区间分别调用迭代方法反转。
递归:定义函数能实现k个节点一组反转链表,参数为(head,k)。
1.base case:以head为头的链表节点数是否小于k;
2.反转前k个节点,保存新头节点;
3.找到head之后的第k个节点,以其为head进行k个节点一组反转,并将其结果作为head的后驱节点;
4 返回新头节点;
递归代码:
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
// write code here
ListNode* b=head;
for(int i=0;i<k;i++){
if(b==nullptr) return head;
b =b->next;
}
ListNode* newhead=reverse(head,b);
head->next =reverseKGroup(b,k);
return newhead;
}
ListNode* reverse(ListNode* start,ListNode* end){
ListNode* pre=nullptr;
ListNode* cur=start;
ListNode* nxt=start;
while(cur!=end){
nxt =cur->next;
cur->next=pre;
pre=cur;
cur=nxt;
}
return pre;
}
};