题目
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-linked-list-ii
思路
- 查找到第m-1结点和第n+1个结点,分别记为pre和post。注意一头一尾的特殊情况,此题的链表是不带头指针的,若m==1,则在head结点前增设头结点。
- 利用头插法将第m个至第n个结点进行反转。
Notes:
1. 若m=1,则应将head指针指向pre->next,否则解答错误。如1->2->3,当m=1,n=2时,反转结果为2->1->3,但是head结点指向值为1的结点,返回结果为1->3解答错误。
2. 若m=1时,要增设头结点。
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseBetween(struct ListNode* head, int m, int n){
if(head==NULL) return NULL;
struct ListNode *pre=NULL,*post=NULL;
struct ListNode *p=head;//工作指针
int len=0;
while(p){
len++;
if(len==m-1){
pre=p;//pre指向第m-1个结点
}
if(len==n+1){
post=p;//post指向第n+1个结点
break;
}
p=p->next;
}
if(!pre){ //若m==1 即第m个结点前无前驱结点,则增设头结点
pre=(struct ListNode*)malloc(sizeof(struct ListNode));
pre->next=head;
}
p=pre->next;//头插法的工作指针
struct ListNode *tmp=NULL;//暂存下一个要遍历的结点
pre->next=post;
while(p!=post){
tmp=p->next;
p->next=pre->next;
pre->next=p;
p=tmp;
}
if(m==1){
head=pre->next;
free(pre); //释放增设的头结点空间
}
return head;
}