206反转链表
206. 反转链表
题解(递归和迭代):
class Solution {
public:
ListNode* reverseList(ListNode* head) {
//递归
/*
//链表节点小于2,返回
if(head == nullptr || head->next == nullptr)
return head;
//递归下一节点链表
ListNode *p = reverseList(head->next);
//反转两个节点
head->next->next = head;
head->next = nullptr;
//返回反转后的头节点
return p;
*/
//迭代
ListNode *p = head;
ListNode *q = new ListNode(0),*tmp = q;
链表节点小于2,返回
if(p == nullptr || p->next == nullptr)
return p;
else{
//q为p的下一节点,因为修改了q的指针后,链表就断开了,所以用tmp保存q的下一节点
q = p->next;
tmp = q->next;
//头节点处理
q->next = p;
p = q;
head->next =nullptr;
//前进
while(tmp != nullptr){
q = tmp;
tmp = tmp->next;
q->next = p;
p = q;
}
return p;
}
}
};
92. 反转链表 II
题解(递归和迭代):
迭代:
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
//迭代
if(left == right)
return head;
else{
//p1记录left前一个节点,p2记录left节点,tmp记录q的下一节点
ListNode *p = head;
ListNode *q = head->next;
ListNode *tmp = new ListNode(),*p1 = tmp,*p2=tmp;
p1->next = p;
int i=1;
//更新p1p2
while(i<left){
p1 = p;
p = p->next;
q = p->next;
++i;
}
p2 = p;
//处理第一次反转
int j = right-left;
if(j>0){
j--;
tmp = q->next;
q->next = p;
}
//处理后续反转
while(j){
p = q;
q = tmp;
tmp = tmp->next;
j--;
q->next = p;
}
//处理断开处的节点指针
p2->next = tmp;
p1->next = q;
if(left==1)
return q;
else
return head;
}
}
};
递归:
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
//递归1
if(left == right)
return head;
//p1记录left前一个节点,q记录left节点,q1记录q的下一节点
ListNode *p = new ListNode(),*q = head,*p1 = p,*q1 = p;
p = head;
p1->next = p;
int i = 1;
while(i<right){
if(i < left){
p1 = p;
p = p->next;
q = p;
}
else{
p = p->next;
q1 = p->next;
}
i++;
}
p->next = nullptr;
ListNode *l = reverse(q);
q->next = q1;
p1->next = l;
if(left==1)
return l;
else
return head;
}
//反转链表
ListNode * reverse(ListNode* head){
if(head == nullptr||head->next == nullptr)
return head;
ListNode *a = reverse(head->next);
head->next->next = head;
head->next = nullptr;
return a;
}
};
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
//递归2
if(left == 1)
return reverse(head,right);
head->next = reverseBetween(head->next,left-1,right-1);
return head;
}
ListNode *p = new ListNode();
//反转链表前n个节点
ListNode* reverse(ListNode* head,int n){
if(n==1){
p = head->next;
return head;
}
ListNode *a = reverse(head->next,n-1);
head->next->next = head;
head->next = p;
return a;
}
};
25. K 个一组翻转链表
迭代思路:借鉴反转链表的迭代方法,将链表分段,每K个一段,就变成了反转链表的问题,只需稍加变动,需要记住每个反转后的链表的头节点和尾节点,以便于将各个分段链表连接起来。
class Solution {
public:
ListNode * reversek(ListNode* head, int k){
ListNode *p = new ListNode(),*q = p,*tmp = p;
p = head;
q = head->next;
tmp = q;
while(k>1){
tmp = tmp->next;
q->next = p;
if(p == head)
p->next = nullptr;
p = q;
q = tmp;
head->next = q;
k--;
}
return p;
}
ListNode* reverseKGroup(ListNode* head, int k) {
int i=0;
ListNode *l = head;
//p11始终指向反转链表的为节点
ListNode *p11 = new ListNode();
ListNode *head1 = new ListNode();
while(l){
//记录每段链表反转前头节点
if(i==0)
head1 = l;
l = l->next;
i++;
//满足条件,准备反转分段链表
if(i==k){
i = 0;
ListNode *tmp = reversek(head1,k);
if(p11 == nullptr)
p11 = head1;
if(p11 != head1){
p11->next = tmp;
p11 = head1;
}
//第一个分段链表需要特殊处理,改变整个链表的头节点
if(head1 == head)
head = tmp;
}
}
return head;
}
};
递归+迭代思路:反转前K个链表用递归解决,然后将各个链表连接起来用迭代
class Solution {
public:
ListNode *p = new ListNode(),*p1 = p;
//反转链表前n个节点
ListNode* reverse(ListNode* head,int n){
if(n==1){
p = head->next;
return head;
}
ListNode *a = reverse(head->next,n-1);
head->next->next = head;
head->next = p;
return a;
}
ListNode* reverseKGroup(ListNode* head, int k) {
int i=0;
ListNode *l = head;
//p11始终指向反转链表的为节点
ListNode *p11 = new ListNode();
ListNode *head1 = new ListNode();
while(l){
//记录每段链表反转前头节点
if(i==0)
head1 = l;
l = l->next;
i++;
if(i==k){
//满足条件,准备反转分段链表
i = 0;
ListNode *tmp = reverse(head1,k);
if(p11 == nullptr)
p11 = head1;
if(p11 != head1){
p11->next = tmp;
p11 = head1;
}
//第一个分段链表需要特殊处理,改变整个链表的头节点
if(head1 == head)
head = tmp;
}
}
//如果刚好被整分,直接返回修改过的头节点,否则需要将剩下的部分链接到p11(反转链表为指针)上
return head;
}
};
纯递归:画图太麻烦,看代码自己想像。
class Solution {
public:
ListNode *p = new ListNode(),*p1 = p;
//反转链表前n个节点
ListNode* reverse(ListNode* head,int n){
if(n==1){
//p = head->next;
return head;
}
ListNode *a = reverse(head->next,n-1);
head->next->next = head;
//head->next = p;
return a;
}
ListNode* reverseKGroup(ListNode* head, int k) {
if(head == nullptr)
return nullptr;
ListNode *x = head;
for(int i=0;i<k;++i){
if(x==nullptr)
return head;//最后不足K个节点,直接返回剩下部分的头节点
x = x->next;//x为低k+1个元素
}
//反转前k个节点,h为反转后的头节点,head为反转后的尾节点
ListNode *h = reverse(head,k);
//让先反转的尾节点指向下一次反转的头节点
head->next = reverseKGroup(x,k);
//返回头节点
return h;
}
};