一. 遞歸
1. 參考這個作者寫的太好了,包括解決反轉鏈表的所有思路.
作者:labuladong
鏈接:https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/bu-bu-chai-jie-ru-he-di-gui-di-fan-zhuan-lian-biao/
2. 這題是反轉m到n區間的鏈表,如果將head移動到m=1的位置,則變成反轉前n-m+1個節點,所以關鍵是把這個遞歸寫好.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
//記錄第一個節點反轉後應該連接哪個節點,
//因爲此時的節點反轉後不一定指向NULL了
ListNode* post = NULL;
ListNode* reverseN(ListNode* head, int n) {
//如果n==1,說明不需要反轉,此時直接返回head,
//並且記錄反轉後應該連接哪個節點.
if(n==1) {
post = head->next;
return head;
}
//對於head->next來說,只需要反轉前n-1個節點就夠了.
ListNode* last = reverseN(head->next, n-1);
head->next->next = head;
//讓反轉後的head和應該連接的之後的點相連接.
head->next = post;
//返回反轉後的頭結點.
return last;
}
ListNode* reverseBetween(ListNode* head, int m, int n) {
//如果m=1, 說明就和反轉前n個節點沒有區別了.
if(m==1) return reverseN(head, n);
//head需要連接以head->next爲節點,m-1和n-1爲區間的節點.
head->next = reverseBetween(head->next,m-1,n-1);
return head;
}
};
二. 迭代
1. 迭代一般思路都很直接.
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
//pre找到m節點的前一個,作爲連接點.
ListNode* pre = dummy;
for(int i=0;i<m-1;i++) {
pre = pre->next;
}
ListNode* cur = pre->next;
ListNode* post = NULL;
ListNode* tmp = cur;
//將m到n的區間進行反轉.
for(int i=0;i<n-m+1;i++) {
ListNode* next = cur->next;
cur->next = post;
post = cur;
cur = next;
}
//最後連接前面和和後面的鏈表.
pre->next = post;
tmp->next = cur;
return dummy->next;
}
};