目录
1 逆置整个链表
#include<stdio.h>
struct ListNode{
int val;
ListNode* next;
ListNode(int x) : val(x) ,next(NULL) {}
};
class Solution{
public:
ListNode* reverseList(ListNode *head){
ListNode *new_head = NULL; //指向新链表头结点指针
while(head){
ListNode *next = head->next; //备份head->next
head->next = new_head; //更新head->next
new_head = head; //移动new_head
head = next; //遍历链表
}
return new_head; //返回新链表结点
}
ListNode* reverseList2(ListNode *head){
ListNode *left = NULL;
ListNode *right = head->next;
while(head){
head->next = left;
left = head;
head = right;
if(right)
right = right->next;
}
return left;
}
};
int main(){
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
Solution solve;
ListNode *head = &a;
printf("Before reverse: \n");
while(head){
printf("%d\n",head->val);
head = head->next;
}
head = solve.reverseList2(&a);
printf("After reverse:\n");
while(head){
printf("%d\n",head->val);
head = head->next;
}
}
2 逆置一个链表的m到n位的元素,返回逆置后的头结点
核心步骤
1.如何找到逆置段的开始和结束位置?
逆置段长度 :len=n-m+1
逆置段开始位置:while(head && –m) head移动m-1个位置
2.几个关键位置
1.逆置前 逆置段开始位置的前一个结点位置: pre_head
2.逆置前 逆置段结束位置的后一个结点位置: modify_list_tail
3.如何连接逆置后的逆置段
分类讨论
逆置段是否包括逆置前链表的头结点?
如果包括头结点,则 pre_head为空,逆置前的头结点变成逆置段逆置后的尾结点
如果不包括头结点,则pre_head不为空,逆置前后整个链表头结点还是链表的头结点,即result指向的位置
if(pre_head){ //如果pre_head不空,说明不是从第一个结点开始逆置的m>1, 就是逆置段不包括头结点result的情况
pre_head->next = new_head; //将逆置链表开始的结点前驱与逆置后的头结点连接
}
else{ //如果逆置段包括了头结点,头结点元素成了逆置段 逆置后的尾元素
result = new_head; //result为逆置前链表头结点的位置,如果pre_head为空,说明 m==1,
//从链表第一个结点开始逆置,链表头结点变为逆置段逆置后的尾结点,逆置前逆置段的尾结点成了逆置后整个链表头结点
}
#include<stdio.h>
struct ListNode{
int val;
ListNode* next;
ListNode(int x) : val(x) ,next(NULL) {}
};
class Solution{
public:
ListNode* reverse_b(ListNode *head,int m,int n){
if(m<1 && m>n){
printf("error data\n");
}
int change_len = n-m+1; //需要逆置的结点个数
ListNode *pre_head = NULL; //初始化开始逆置的结点的前驱
ListNode *result = head; //最终转换后的链表头结点,非特殊情况即为head
while(head && --m){ //将head向前移动m-1个位置,注意如果m=1,pre_head还是为NULL,while循环不执行
pre_head = head; //记录head的前驱
head = head->next;
}
ListNode *modify_list_tail = head; //将modify_list_tail指向当前的head,即逆置段逆置后的链表尾
ListNode *new_head = NULL;
while(head && change_len){ //逆置change_len个结点
ListNode *next = head->next;
head->next = new_head;
new_head = head;
head = next;
change_len--; //每完成一个结点逆置,change_len--
}
modify_list_tail->next = head; //连接逆置后链表尾 与 逆置段的后一个结点
if(pre_head){ //如果pre_head不空,说明不是从第一个结点开始逆置的m>1, 就是逆置段不包括头结点result的情况
pre_head->next = new_head; //将逆置链表开始的结点前驱与逆置后的头结点连接
}
else{ //如果逆置段包括了头结点,头结点元素成了逆置段 逆置后的尾元素
result = new_head; //result为逆置前链表头结点的位置,如果pre_head为空,说明 m==1,
//从链表第一个结点开始逆置,链表头结点变为逆置段逆置后的尾结点,逆置前逆置段的尾结点成了逆置后整个链表头结点
}
return result;
}
};
int main(){
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
Solution solve;
ListNode *head = &a;
printf("Before reverse: \n");
while(head){
printf("%d\n",head->val);
head = head->next;
}
printf("Please Input m and n:\n");
int m,n;
scanf("%d%d",&m,&n);
head = solve.reverse_b(&a,m,n);
printf("After reverse:\n");
while(head){
printf("%d\n",head->val);
head = head->next;
}
}
学习地址
https://www.bilibili.com/video/BV1F4411b7qE?t=2010