11## 题目地址
2+
23https://leetcode.com/problems/reverse-nodes-in-k-group/
34
45## 题目描述
6+
57```
68Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
79
@@ -27,12 +29,14 @@ You may not alter the values in the list's nodes, only nodes itself may be chang
2729- 链表
2830
2931## 思路
30- 题意是以 ` k ` 个nodes为一组进行翻转,返回翻转后的` linked list ` .
3132
32- 从左往右扫描一遍` linked list ` ,扫描过程中,以k为单位把数组分成若干段,对每一段进行翻转。给定首尾nodes,如何对链表进行翻转。
33+ 题意是以 ` k ` 个 nodes 为一组进行翻转,返回翻转后的` linked list ` .
34+
35+ 从左往右扫描一遍` linked list ` ,扫描过程中,以 k 为单位把数组分成若干段,对每一段进行翻转。给定首尾 nodes,如何对链表进行翻转。
36+
37+ 链表的翻转过程,初始化一个为` null ` 的 ` previous node(prev) ` ,然后遍历链表的同时,当前` node (curr) ` 的下一个(next)指向前一个` node(prev) ` ,
38+ 在改变当前 node 的指向之前,用一个临时变量记录当前 node 的下一个` node(curr.next) ` . 即
3339
34- 链表的翻转过程,初始化一个为` null ` 的 ` previous node(prev) ` ,然后遍历链表的同时,当前` node (curr) ` 的下一个(next)指向前一个` node(prev) ` ,
35- 在改变当前node的指向之前,用一个临时变量记录当前node的下一个` node(curr.next) ` . 即
3640```
3741ListNode temp = curr.next;
3842curr.next = prev;
@@ -50,40 +54,41 @@ curr = temp;
5054
51552 . 用一个` start ` 变量记录当前分组的起始节点位置的前一个节点
5256
53- 3 . 用一个` end ` 变量记录要翻转的最后一个节点位置
57+ 3 . 用一个` end ` 变量记录要翻转的最后一个节点位置
5458
55594 . 翻转一组(` k个nodes ` )即` (start, end) - start and end exclusively ` 。
5660
57615 . 翻转后,` start ` 指向翻转后链表, 区间` (start,end) ` 中的最后一个节点, 返回` start ` 节点。
5862
59636 . 如果不需要翻转,` end ` 就往后移动一个(` end=end.next ` ),每一次移动,都要` count+1 ` .
6064
61- 如图所示 步骤4和5 : 翻转区间链表区间` (start, end) `
65+ 如图所示 步骤 4 和 5 : 翻转区间链表区间` (start, end) `
6266
6367![ reverse linked list range in (start, end)] ( ../assets/problems/25.reverse-nodes-in-k-groups-3.png )
6468
65-
6669举例如图,` head=[1,2,3,4,5,6,7,8], k = 3 `
6770
68-
6971![ reverse k nodes in linked list] ( ../assets/problems/25.reverse-nodes-in-k-groups-2.PNG )
7072
71-
72- > ** NOTE** : 一般情况下对链表的操作,都有可能会引入一个新的` dummy node ` ,因为` head ` 有可能会改变。这里` head 从1->3 ` ,
73- ` dummy (List(0)) ` 保持不变。
73+ > ** NOTE** : 一般情况下对链表的操作,都有可能会引入一个新的` dummy node ` ,因为` head ` 有可能会改变。这里` head 从1->3 ` ,
74+ > ` dummy (List(0)) ` 保持不变。
7475
7576#### 复杂度分析
76- - * 时间复杂度:* ` O(n) - n is number of Linked List `
77- - * 空间复杂度:* ` O(1) `
77+
78+ - _ 时间复杂度:_ ` O(n) - n is number of Linked List `
79+ - _ 空间复杂度:_ ` O(1) `
7880
7981## 关键点分析
80- 1 . 创建一个dummy node
81- 2 . 对链表以k为单位进行分组,记录每一组的起始和最后节点位置
82+
83+ 1 . 创建一个 dummy node
84+ 2 . 对链表以 k 为单位进行分组,记录每一组的起始和最后节点位置
82853 . 对每一组进行翻转,更换起始和最后的位置
83864 . 返回` dummy.next ` .
8487
8588## 代码 (` Java/Python3/javascript ` )
86- * Java Code*
89+
90+ _ Java Code_
91+
8792``` java
8893class ReverseKGroupsLinkedList {
8994 public ListNode reverseKGroup (ListNode head , int k ) {
@@ -142,7 +147,8 @@ class ReverseKGroupsLinkedList {
142147}
143148```
144149
145- * Python3 Cose*
150+ _ Python3 Cose_
151+
146152``` python
147153class Solution :
148154 def reverseKGroup (self , head : ListNode, k : int ) -> ListNode:
@@ -181,79 +187,131 @@ class Solution:
181187
182188```
183189
184- * javascript code*
190+ _ javascript code_
191+
185192``` js
186193/**
187194 * @param {ListNode} head
188195 * @param {number} k
189196 * @return {ListNode}
190197 */
191- var reverseKGroup = function (head , k ) {
198+ var reverseKGroup = function (head , k ) {
192199 // 标兵
193- let dummy = new ListNode ()
194- dummy .next = head
195- let [start, end] = [dummy, dummy .next ]
196- let count = 0
197- while (end) {
198- count++
200+ let dummy = new ListNode ();
201+ dummy .next = head;
202+ let [start, end] = [dummy, dummy .next ];
203+ let count = 0 ;
204+ while (end) {
205+ count++ ;
199206 if (count % k === 0 ) {
200- start = reverseList (start, end .next )
201- end = start .next
207+ start = reverseList (start, end .next );
208+ end = start .next ;
202209 } else {
203- end = end .next
210+ end = end .next ;
204211 }
205212 }
206- return dummy .next
213+ return dummy .next ;
207214
208215 // 翻转stat -> end的链表
209216 function reverseList (start , end ) {
210- let [pre, cur] = [start, start .next ]
211- const first = cur
212- while (cur !== end) {
213- let next = cur .next
214- cur .next = pre
215- pre = cur
216- cur = next
217+ let [pre, cur] = [start, start .next ];
218+ const first = cur;
219+ while (cur !== end) {
220+ let next = cur .next ;
221+ cur .next = pre;
222+ pre = cur;
223+ cur = next;
217224 }
218- start .next = pre
219- first .next = cur
220- return first
225+ start .next = pre;
226+ first .next = cur;
227+ return first;
221228 }
222229};
223-
224230```
225231
226232## 参考(References)
233+
227234- [ Leetcode Discussion (yellowstone)] ( https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11440/Non-recursive-Java-solution-and-idea )
228235
229- ## 扩展
236+ ## 扩展 1
230237
231238- 要求从后往前以` k ` 个为一组进行翻转。** (字节跳动(ByteDance)面试题)**
232239
233- 例子,` 1->2->3->4->5->6->7->8, k = 3 ` ,
240+ 例子,` 1->2->3->4->5->6->7->8, k = 3 ` ,
241+
242+ 从后往前以` k=3 ` 为一组,
234243
235- 从后往前以` k=3 ` 为一组,
236- - ` 6->7->8 ` 为一组翻转为` 8->7->6 ` ,
237- - ` 3->4->5 ` 为一组翻转为` 5->4->3 ` .
238- - ` 1->2 ` 只有2个nodes少于` k=3 ` 个,不翻转。
244+ - ` 6->7->8 ` 为一组翻转为` 8->7->6 ` ,
245+ - ` 3->4->5 ` 为一组翻转为` 5->4->3 ` .
246+ - ` 1->2 ` 只有 2 个 nodes 少于` k=3 ` 个,不翻转。
239247
240- 最后返回: ` 1->2->5->4->3->8->7->6 `
248+ 最后返回: ` 1->2->5->4->3->8->7->6 `
241249
242250这里的思路跟从前往后以` k ` 个为一组进行翻转类似,可以进行预处理:
243251
2442521 . 翻转链表
245253
246- 2 . 对翻转后的链表进行从前往后以k为一组翻转 。
254+ 2 . 对翻转后的链表进行从前往后以 k 为一组翻转 。
247255
248- 3 . 翻转步骤2中得到的链表 。
256+ 3 . 翻转步骤 2 中得到的链表 。
249257
250258例子:` 1->2->3->4->5->6->7->8, k = 3 `
251259
2522601 . 翻转链表得到:` 8->7->6->5->4->3->2->1 `
253261
254- 2 . 以k为一组翻转: ` 6->7->8->3->4->5->2->1 `
262+ 2 . 以 k 为一组翻转: ` 6->7->8->3->4->5->2->1 `
263+
264+ 3 . 翻转步骤#2 链表: ` 1->2->5->4->3->8->7->6 `
265+
266+ ## 扩展 2
267+
268+ 如果这道题你按照 [ 92.reverse-linked-list-ii] ( ./92.reverse-linked-list-ii.md ) 提到的 ` p1, p2, p3, p4 ` (四点法) 的思路来思考的话会很清晰。
269+
270+ 代码如下(Python):
271+
272+ ``` py
273+
274+ class Solution :
275+ def reverseKGroup (self , head : ListNode, k : int ) -> ListNode:
276+ if head is None or k < 2 :
277+ return head
278+ dummy = ListNode(0 )
279+ dummy.next = head
280+ pre = dummy
281+ cur = head
282+ count = 0
283+ while cur:
284+ count += 1
285+ if count % k == 0 :
286+ pre = self .reverse(pre, cur.next)
287+ # end 调到下一个位置
288+ cur = pre.next
289+ else :
290+ cur = cur.next
291+ return dummy.next
292+ # (p1, p4) 左右都开放
293+
294+ def reverse (self , p1 , p4 ):
295+ prev, curr = p1, p1.next
296+ p2 = curr
297+ # 反转
298+ while curr != p4:
299+ next = curr.next
300+ curr.next = prev
301+ prev = curr
302+ curr = next
303+ # 将反转后的链表添加到原链表中
304+ # prev 相当于 p3
305+ p1.next = prev
306+ p2.next = p4
307+ # 返回反转前的头, 也就是反转后的尾部
308+ return p2
309+
310+ # @lc code=end
311+
312+ ```
255313
256- 3 . 翻转步骤 # 2 链表: ` 1->2->5->4->3->8->7->6 `
314+ ## 相关题目
257315
258- ## 类似题目
259- - [ Swap Nodes in Pairs ] ( https://leetcode.com/problems/swap-nodes-in-pairs/ )
316+ - [ 92.reverse-linked-list-ii ] ( ./92.reverse-linked-list-ii.md )
317+ - [ 206.reverse-linked-list ] ( ./206.reverse-linked-list.md )
0 commit comments