Skip to content

Commit 3e6a534

Browse files
snowanazl397985856
authored andcommitted
feat: Add LC 25 reverse nodes in k group (#156)
1 parent 35d8ef9 commit 3e6a534

7 files changed

+423
-0
lines changed

README.en.md

+1
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ The data structures mainly includes:
216216

217217
- [0004.median-of-two-sorted-array](./problems/4.median-of-two-sorted-array.md) 🆕
218218
- [0023.merge-k-sorted-lists](./problems/23.merge-k-sorted-lists.md)
219+
- [0025.reverse-nodes-in-k-group](./problems/25.reverse-nodes-in-k-groups-en.md) 🆕
219220
- [0032.longest-valid-parentheses](./problems/32.longest-valid-parentheses.md) 🆕
220221
- [0042.trapping-rain-water](./problems/42.trapping-rain-water.md)
221222
- [0124.binary-tree-maximum-path-sum](./problems/124.binary-tree-maximum-path-sum.md)

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。
220220

221221
- [0004.median-of-two-sorted-array](./problems/4.median-of-two-sorted-array.md) 🆕
222222
- [0023.merge-k-sorted-lists](./problems/23.merge-k-sorted-lists.md)
223+
- [0025.reverse-nodes-in-k-group](./problems/25.reverse-nodes-in-k-groups-cn.md) 🆕
223224
- [0032.longest-valid-parentheses](./problems/32.longest-valid-parentheses.md) 🆕
224225
- [0042.trapping-rain-water](./problems/42.trapping-rain-water.md)
225226
- [0124.binary-tree-maximum-path-sum](./problems/124.binary-tree-maximum-path-sum.md)
Loading
Loading
Loading
+207
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
## 题目地址
2+
https://leetcode.com/problems/reverse-nodes-in-k-group/
3+
4+
## 题目描述
5+
```
6+
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.
7+
8+
k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.
9+
10+
Example:
11+
12+
Given this linked list: 1->2->3->4->5
13+
14+
For k = 2, you should return: 2->1->4->3->5
15+
16+
For k = 3, you should return: 3->2->1->4->5
17+
18+
Note:
19+
20+
Only constant extra memory is allowed.
21+
You may not alter the values in the list's nodes, only nodes itself may be changed.
22+
23+
```
24+
25+
## 思路
26+
题意是以 `k` 个nodes为一组进行翻转,返回翻转后的`linked list`.
27+
28+
从左往右扫描一遍`linked list`,扫描过程中,以k为单位把数组分成若干段,对每一段进行翻转。给定首尾nodes,如何对链表进行翻转。
29+
30+
链表的翻转过程,初始化一个为`null ``previous node(prev)`,然后遍历链表的同时,当前`node (curr)`的下一个(next)指向前一个`node(prev)`
31+
在改变当前node的指向之前,用一个临时变量记录当前node的下一个`node(curr.next)`. 即
32+
```
33+
ListNode temp = curr.next;
34+
curr.next = prev;
35+
prev = curr;
36+
curr = temp;
37+
```
38+
39+
举例如图:翻转整个链表 `1->2->3->4->null` -> `4->3->2->1->null`
40+
41+
![reverse linked list](../assets/problems/25.reverse-nodes-in-k-groups-1.PNG)
42+
43+
这里是对每一组(`k个nodes`)进行翻转,
44+
45+
1. 先分组,用一个`count`变量记录当前节点的个数
46+
47+
2. 用一个`start` 变量记录当前分组的起始节点位置的前一个节点
48+
49+
3. 用一个`end `变量记录要翻转的最后一个节点位置
50+
51+
4. 翻转一组(`k个nodes`)即`(start, end) - start and end exclusively`
52+
53+
5. 翻转后,`start`指向翻转后链表, 区间`(start,end)`中的最后一个节点, 返回`start` 节点。
54+
55+
6. 如果不需要翻转,`end` 就往后移动一个(`end=end.next`),每一次移动,都要`count+1`.
56+
57+
如图所示 步骤4和5: 翻转区间链表区间`(start, end)`
58+
59+
![reverse linked list range in (start, end)](../assets/problems/25.reverse-nodes-in-k-groups-3.png)
60+
61+
62+
举例如图,`head=[1,2,3,4,5,6,7,8], k = 3`
63+
64+
65+
![reverse k nodes in linked list](../assets/problems/25.reverse-nodes-in-k-groups-2.PNG)
66+
67+
68+
>**NOTE**: 一般情况下对链表的操作,都有可能会引入一个新的`dummy node`,因为`head`有可能会改变。这里`head 从1->3`,
69+
`dummy (List(0)) `保持不变。
70+
71+
#### 复杂度分析
72+
- *时间复杂度:* `O(n) - n is number of Linked List`
73+
- *空间复杂度:* `O(1)`
74+
75+
## 关键点分析
76+
1. 创建一个dummy node
77+
2. 对链表以k为单位进行分组,记录每一组的起始和最后节点位置
78+
3. 对每一组进行翻转,更换起始和最后的位置
79+
4. 返回`dummy.next`.
80+
81+
## 代码 (`Java/Python3`)
82+
*Java Code*
83+
```java
84+
class ReverseKGroupsLinkedList {
85+
public ListNode reverseKGroup(ListNode head, int k) {
86+
if (head == null || k == 1) {
87+
return head;
88+
}
89+
ListNode dummy = new ListNode(0);
90+
dummy.next = head;
91+
92+
ListNode start = dummy;
93+
ListNode end = head;
94+
int count = 0;
95+
while (end != null) {
96+
count++;
97+
// group
98+
if (count % k == 0) {
99+
// reverse linked list (start, end]
100+
start = reverse(start, end.next);
101+
end = start.next;
102+
} else {
103+
end = end.next;
104+
}
105+
}
106+
return dummy.next;
107+
}
108+
109+
/**
110+
* reverse linked list from range (start, end), return last node.
111+
* for example:
112+
* 0->1->2->3->4->5->6->7->8
113+
* | |
114+
* start end
115+
*
116+
* After call start = reverse(start, end)
117+
*
118+
* 0->3->2->1->4->5->6->7->8
119+
* | |
120+
* start end
121+
* first
122+
*
123+
*/
124+
private ListNode reverse(ListNode start, ListNode end) {
125+
ListNode curr = start.next;
126+
ListNode prev = start;
127+
ListNode first = curr;
128+
while (curr != end){
129+
ListNode temp = curr.next;
130+
curr.next = prev;
131+
prev = curr;
132+
curr = temp;
133+
}
134+
start.next = prev;
135+
first.next = curr;
136+
return first;
137+
}
138+
}
139+
```
140+
141+
*Python3 Cose*
142+
```python
143+
class Solution:
144+
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
145+
if head is None or k < 2:
146+
return head
147+
dummy = ListNode(0)
148+
dummy.next = head
149+
start = dummy
150+
end = head
151+
count = 0
152+
while end:
153+
count += 1
154+
if count % k == 0:
155+
start = self.reverse(start, end.next)
156+
end = start.next
157+
else:
158+
end = end.next
159+
return dummy.next
160+
161+
def reverse(self, start, end):
162+
prev, curr = start, start.next
163+
first = curr
164+
while curr != end:
165+
temp = curr.next
166+
curr.next = prev
167+
prev = curr
168+
curr = temp
169+
start.next = prev
170+
first.next = curr
171+
return first
172+
```
173+
174+
## 参考(References)
175+
- [Leetcode Discussion (yellowstone)](https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11440/Non-recursive-Java-solution-and-idea)
176+
177+
## 扩展
178+
179+
- 要求从后往前以`k`个为一组进行翻转。**(字节跳动(ByteDance)面试题)**
180+
181+
例子,`1->2->3->4->5->6->7->8, k = 3`,
182+
183+
从后往前以`k=3`为一组,
184+
- `6->7->8` 为一组翻转为`8->7->6`
185+
- `3->4->5`为一组翻转为`5->4->3`.
186+
- `1->2`只有2个nodes少于`k=3`个,不翻转。
187+
188+
最后返回: `1->2->5->4->3->8->7->6`
189+
190+
这里的思路跟从前往后以`k`个为一组进行翻转类似,可以进行预处理:
191+
192+
1. 翻转链表
193+
194+
2. 对翻转后的链表进行从前往后以k为一组翻转。
195+
196+
3. 翻转步骤2中得到的链表。
197+
198+
例子:`1->2->3->4->5->6->7->8, k = 3`
199+
200+
1. 翻转链表得到:`8->7->6->5->4->3->2->1`
201+
202+
2. 以k为一组翻转: `6->7->8->3->4->5->2->1`
203+
204+
3. 翻转步骤#2链表: `1->2->5->4->3->8->7->6`
205+
206+
## 类似题目
207+
- [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/)

0 commit comments

Comments
 (0)