0. 题干
leetcode 92,Reverse Linked List II,难度medium
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
1. 代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode* pre = NULL;
ListNode* cur = head;
ListNode* pre0,*cur0;
unsigned int count = 1;
while(cur != NULL && count <= n){
//当cur为m时,记录一下当前cur和pre
if(count == m)//在头节点,则记录当前pre和cur供后续连接使用
{
pre0 = pre;
cur0 = cur;
}
//当cur在(m,n]之间时,反转链表
if(count > m && count <= n)
{
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
else //常规迭代处理
{
pre = cur;
cur = cur->next;
}
//常规处理
++count;
}
//最后的链接操作
//将pre0的next指向第n元素,此时pre指向n,cur指向原始链表中n的下一个元素
if(pre0 == NULL) head = pre;
else pre0->next = pre;
//将指向m的cur0的next指向n后第一个元素
cur0->next = cur;
return head;
}
};
2. 详述代码流程
详述代码逻辑:(还是假设有五个结点,假设m=2,n=4)
pre初始化为NULL,cur存储头指针的地址(此处即结点1的地址),count初始化为1
刚进入while循环,此时count=1,m=2,所以此时连续跳过两个if判断语句,
pre递增指向结点1,cur指向结点2,count递增为2;
此时再次进入while循环,count=m=2,记录下pre0指向结点1,cur0指向结点2;
跳过下一个if语句判断,pre递增指向结点2,cur指向结点3,count递增为3
然后再进入while循环,进入第二个if判断语句,此时temp备份一个结点位置,指向结点4,
结点3,指回结点2;
pre递增指向结点3,cur递增指向结点4,count递增为4,再次进入while循环,进入第二个if 判断语句,备份temp指向结点5,结点4指回结点3,(至此,符合题意,结点2、结点3、结点4实现链表反转)
继续pre递增 指向结点4,cur指向结点5,count递增为5,while循环结束;
最后处理下两头的连接,pre0存储了结点1的位置,结点1指向结点4,;cur0存储了结点2的位置,结点2指向结点5,即实现链表: 1->4->3->2->5->NULL
补充下边界条件的理解:
假设m=1(n还是4),那么pre0指向NULL,cur0存储结点1位置,所以代码里直接让head=pre,就上面的描述,最终pre递增到了结点4,结点4即为头节点;
假设n=5(m还是等于2),那么上面的while循环还没结束,进入while循环的第二个if判断,temp指向NULL,结点5指回结点4,pre递增为结点5位置,cur递增指向NULL;然后进入最后的两头连接,
(pre0存储结点1的位置,cur0存储结点2的位置),结点1指向结点5,结点2指向NULL,即实现了
1->5->4->3->2->NULL。