Reverse Linked List II Reverse a linked list from position m to n. Do
it in-place and in one-pass.For example: Given 1->2->3->4->5->NULL, m = 2 and n = 4,
return 1->4->3->2->5->NULL.
Note: Given m, n satisfy the following condition: 1 ≤ m ≤ n ≤ length
of list.
将[m,n]之间的结点反转
思路一
类似于将整个链表反转,pPrev,pNode,为头两个结点,每次将pNode指向pPre,再将pPre和pNode向后移动即可。反转链表
在本例中,结束的条件不是pNode ==NULL,而是结点的数目n-m+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) {
int k = n-m+1;
ListNode *new_head = new ListNode(0);
new_head->next = head;
ListNode* pre = new_head;
//pre实际上是第m-1个结点
for (int i = 0; i < m - 1; i++)
pre = pre -> next;
pre->next = reverseAll(pre->next, k);
return new_head->next;
}
ListNode* reverseAll(ListNode* p1, int k){
ListNode* pNode= p1;
ListNode* pPrev=NULL; //当前节点的前一个结点
ListNode* pNext;
//每次将pNode指向pPre;
while(k--){
pNext = pNode->next;
pNode->next = pPrev;
//移动pNode和pPre
pPrev = pNode;
pNode =pNext;
}
p1->next = pNode; //实际上是第n+1个结点
return pPrev;
}
};
上面的reverseAll函数如果将形参k去掉,while变成while(pNode!=NULL)则是一个普通的反转链表。
注意while退出时,pNode指向的是第n+1个结点(有k的情况)或是NULL(没有k的情况)。这是需要把原始的头结点p1->next = pNode;
另一个小的trick就是不用考虑m=1的特殊情况,只需要再加一个new_head的头结点即可。
0ms AC
思路二
Jianchao’s Blog 大神每次都能给出牛逼的思路
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode* new_head = new ListNode(0);
new_head -> next = head;
ListNode* pre = new_head;
for (int i = 0; i < m - 1; i++)
pre = pre -> next;
ListNode* cur = pre -> next;
for (int i = 0; i < n - m; i++) {
ListNode* move = cur -> next;
cur -> next = move -> next;
move -> next = pre -> next;
pre -> next = move;
}
return new_head -> next;
}
};
pre指向第m-1个结点,curr是当前的结点,move是m+1个结点,我们每次都将curr的next指向curr的next的next,将move指向curr,将pre指向move。注意pre是不动的,每次因为curr的next都在变,所以一直移动。
4ms AC