【链表】206. Reverse Linked List; 92. Reverse Linked List II;25. Reverse Nodes in k-Group
问题:
206.链表反转。
Example: Input: 1->2->3->4->5->NULL Output: 5->4->3->2->1->NULL
92.指定区间链表反转。
Note: 1 ≤ m ≤ n ≤ length of list. Example: Input: 1->2->3->4->5->NULL, m = 2, n = 4 Output: 1->4->3->2->5->NULL
25. 每连续k个元素进行反转。
Example 1: Input: head = [1,2,3,4,5], k = 2 Output: [2,1,4,3,5] Example 2: Input: head = [1,2,3,4,5], k = 3 Output: [3,2,1,4,5] Example 3: Input: head = [1,2,3,4,5], k = 1 Output: [1,2,3,4,5] Example 4: Input: head = [1], k = 1 Output: [1] Constraints: The number of nodes in the list is in the range sz. 1 <= sz <= 5000 0 <= Node.val <= 1000 1 <= k <= sz
解法:Recursion(递归)Iteration(迭代)
206.
1.递归获得2~6,反转后的结果。
2.将2->next指针,指向1:
由于原来1->next=2,因此 (1->next)->next = 1
3.将1->next指向NULL
BASE:
只有一个节点 or 0个节点,return head
代码参考:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode() : val(0), next(nullptr) {} 7 * ListNode(int x) : val(x), next(nullptr) {} 8 * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 * }; 10 */ 11 class Solution { 12 public: 13 //1->reverseList(2<-3<-4<-5) 14 ListNode* reverseList(ListNode* head) { 15 //base 16 if(!head || !head->next) return head; 17 //recursion 18 ListNode* newhead = reverseList(head->next); 19 //OPT 20 head->next->next = head; 21 head->next = nullptr; 22 return newhead; 23 } 24 };
92.
先解决,如何反转前n个节点。
reverseN(ListNode* head, int n)
相较于206,多了第n个节点之后的,不需要反转的节点successor
因此,比206多出的处理:
- ★BASE:
- 记录successor节点,n==1的时候,只剩一个节点
- successor = head->next
- recursion后的 ★OPT:
- head->next=successor
即,代码为:
1 ListNode* reverseN(ListNode* head, int n) { 2 //base 3 if(n==1) { 4 successor = head->next;//★BASE 5 return head; 6 } 7 //recursion 8 ListNode* newhead = reverseN(head->next, n-1); 9 //OPT 10 head->next->next = head; 11 head->next = successor;//★OPT 12 return newhead; 13 }
接下来,解决 从第m个开始,
递归到m==1,则变成上面的问题,直接调用reverseN即可。
其他情况,依次递归,不用更改任何指针。
⚠️ 注意:从第0个移动到第m个时的递归中,
返回值:当前的新头。所以,head->next=上次递归的结果。
代码为:
1 ListNode* reverseBetween(ListNode* head, int m, int n) { 2 if(!head || !head->next) return head; 3 if(m==1) return reverseN(head, n); 4 head->next = reverseBetween(head->next, m-1, n-1); 5 return head; 6 }
代码参考:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode() : val(0), next(nullptr) {} 7 * ListNode(int x) : val(x), next(nullptr) {} 8 * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 * }; 10 */ 11 class Solution { 12 public: 13 ListNode* successor; 14 ListNode* reverseBetween(ListNode* head, int m, int n) { 15 if(!head || !head->next) return head; 16 if(m==1) return reverseN(head, n); 17 head->next = reverseBetween(head->next, m-1, n-1); 18 return head; 19 } 20 ListNode* reverseN(ListNode* head, int n) { 21 //base 22 if(n==1) { 23 successor = head->next; 24 return head; 25 } 26 //recursion 27 ListNode* newhead = reverseN(head->next, n-1); 28 //OPT 29 head->next->next = head; 30 head->next = successor; 31 return newhead; 32 } 33 };
25.
用迭代(Iteration)的方法实现[a,b)的反转
如下图,反转 [1,NULL)
![](https://img2020.cnblogs.com/blog/501857/202011/501857-20201102190609510-1217993052.png)
1 ListNode* reverse(ListNode* a, ListNode* b) { 2 ListNode *cur = a, *pre = NULL, *nxt = a; 3 while(cur!=b) { 4 nxt = cur->next; 5 cur->next = pre; 6 pre = cur; 7 cur = nxt; 8 } 9 return pre; 10 }
再用递归,求出第一组[a,b)反转后,连接到后面[b,...)已经反转完成的所有。
如下图k=2,[1,3)
⚠️ 注意:如果不足k个元素,则不进行反转。
1 ListNode* reverseKGroup(ListNode* head, int k) { 2 if(!head) return head; 3 ListNode *a=head, *b=head; 4 for(int i=0; i<k; i++) { 5 if(b==NULL) return head;//不足k个元素,不进行反转 6 b = b->next; 7 } 8 //反转[a,b) 9 ListNode* newhead = reverse(a, b); 10 //连接反转后的[a,b),和反转的后面所有元素[b,...) 11 a->next = reverseKGroup(b, k); 12 return newhead; 13 }
完整代码参考:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode() : val(0), next(nullptr) {} 7 * ListNode(int x) : val(x), next(nullptr) {} 8 * ListNode(int x, ListNode *next) : val(x), next(next) {} 9 * }; 10 */ 11 class Solution { 12 public: 13 //[a,b) -> [a,NULL) 14 ListNode* reverse(ListNode* a, ListNode* b) { 15 ListNode *cur = a, *pre = NULL, *nxt = a; 16 while(cur!=b) { 17 nxt = cur->next; 18 cur->next = pre; 19 pre = cur; 20 cur = nxt; 21 } 22 return pre; 23 } 24 ListNode* reverseKGroup(ListNode* head, int k) { 25 if(!head) return head; 26 ListNode *a=head, *b=head; 27 for(int i=0; i<k; i++) { 28 if(b==NULL) return head; 29 b = b->next; 30 } 31 ListNode* newhead = reverse(a, b); 32 a->next = reverseKGroup(b, k); 33 return newhead; 34 } 35 };