Skip to content

Commit 2b4fe3e

Browse files
author
xiaowei wan
committed
Add LC 25 reverse nodes in k group
1 parent 72ab477 commit 2b4fe3e

File tree

6 files changed

+377
-0
lines changed

6 files changed

+377
-0
lines changed

README.en.md

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
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.next, end]`
52+
53+
5. 翻转后,`start`指向翻转后链表的最后一个节点,`end`指向`start`的下一个节点(`end=start.next`).
54+
55+
6. 如果不需要翻转,`end` 就往后移动一个(`end=end.next`),每一次移动,都要`count+1`.
56+
57+
举例如图,`head=[1,2,3,4,5,6,7,8], k = 3`
58+
59+
60+
![reverse k nodes in linked list](../assets/problems/25.reverse-nodes-in-k-groups-2.PNG)
61+
62+
63+
>**NOTE**: 一般情况下对链表的操作,都有可能会引入一个新的`dummy node`,因为`head`有可能会改变。这里`head 从1->3`,
64+
`dummy (List(0)) `保持不变。
65+
66+
#### 复杂度分析
67+
- *时间复杂度:* `O(n) - n is number of Linked List`
68+
- *空间复杂度:* `O(1)`
69+
70+
## 关键点分析
71+
1. 创建一个dummy node
72+
2. 对链表以k为单位进行分组,记录每一组的起始和最后节点位置
73+
3. 对每一组进行翻转,更换起始和最后的位置
74+
4. 返回`dummy.next`.
75+
76+
## 代码 (`Java/Python3`)
77+
*Java Code*
78+
```java
79+
class ReverseKGroupsLinkedList {
80+
public ListNode reverseKGroup(ListNode head, int k) {
81+
if (head == null || k == 1) {
82+
return head;
83+
}
84+
ListNode dummy = new ListNode(0);
85+
dummy.next = head;
86+
87+
ListNode start = dummy;
88+
ListNode end = head;
89+
int count = 0;
90+
while (end != null) {
91+
count++;
92+
// group
93+
if (count % k == 0) {
94+
// reverse linked list (start, end]
95+
start = reverse(start, end.next);
96+
end = start.next;
97+
} else {
98+
end = end.next;
99+
}
100+
}
101+
return dummy.next;
102+
}
103+
104+
// reverse linked list from range (start, end], return last node.
105+
private ListNode reverse(ListNode pre, ListNode next) {
106+
ListNode last = pre.next;
107+
ListNode curr = last.next;
108+
109+
while (curr != next) {
110+
last.next = curr.next;
111+
curr.next = pre.next;
112+
pre.next = curr;
113+
curr = last.next;
114+
}
115+
return last;
116+
}
117+
}
118+
```
119+
120+
*Python3 Cose*
121+
```python
122+
class Solution:
123+
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
124+
if head is None or k < 2:
125+
return head
126+
dummy = ListNode(0)
127+
dummy.next = head
128+
start = dummy
129+
end = head
130+
count = 0
131+
while end:
132+
count += 1
133+
if count % k == 0:
134+
start = self.reverse(start, end.next)
135+
end = start.next
136+
else:
137+
end = end.next
138+
return dummy.next
139+
140+
def reverse(self, start, end):
141+
last = start.next
142+
curr = last.next
143+
while curr != end:
144+
last.next = curr.next
145+
curr.next = start.next
146+
start.next = curr
147+
curr = last.next
148+
return last
149+
```
150+
151+
## 参考(References)
152+
- [Leetcode Discussion (yellowstone)](https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11440/Non-recursive-Java-solution-and-idea)
153+
154+
## 扩展
155+
156+
- 要求从后往前以`k`个为一组进行翻转。**(字节跳动(ByteDance)面试题)**
157+
158+
例子,`1->2->3->4->5->6->7->8, k = 3`,
159+
160+
从后往前以`k=3`为一组,
161+
- `6->7->8` 为一组翻转为`8->7->6`
162+
- `3->4->5`为一组翻转为`5->4->3`.
163+
- `1->2`只有2个nodes少于`k=3`个,不翻转。
164+
165+
最后返回: `1->2->5->4->3->8->7->6`
166+
167+
这里的思路跟从前往后以`k`个为一组进行翻转类似,可以进行预处理:
168+
169+
1. 翻转链表
170+
171+
2. 对翻转后的链表进行从前往后以k为一组翻转。
172+
173+
3. 翻转步骤2中得到的链表。
174+
175+
例子:`1->2->3->4->5->6->7->8, k = 3`
176+
177+
1. 翻转链表得到:`8->7->6->5->4->3->2->1`
178+
179+
2. 以k为一组翻转: `6->7->8->3->4->5->2->1`
180+
181+
3. 翻转步骤#2链表: `1->2->5->4->3->8->7->6`
182+
183+
## 类似题目
184+
- [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/)
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
## Problem
2+
https://leetcode.com/problems/reverse-nodes-in-k-group/
3+
4+
## Problem Description
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+
## Solution
26+
Traverse `linked list` from left to right, during traverse, group nodes in k, then reverse each group.
27+
How to reverse a linked list given start, end node?
28+
29+
Reverse linked list:
30+
31+
1. Initial a prev node `null`
32+
33+
2. For each move, use temp node to keep current next node.
34+
35+
3. During traverse, update current node pointing to previous node, update previous pointing to current node
36+
37+
4. Update current to temp
38+
39+
```
40+
ListNode temp = curr.next;
41+
curr.next = prev;
42+
prev = curr;
43+
curr = temp;
44+
```
45+
46+
For example(as below pic): reverse the whole linked list `1->2->3->4->null` -> `4->3->2->1->null`
47+
48+
![reverse linked list](../assets/problems/25.reverse-nodes-in-k-groups-1.PNG)
49+
50+
Here Reverse each group(`k nodes`):
51+
52+
1. First group, use `count` keep track linked list counts when traverse linked list
53+
54+
2. Use `start` to keep track each group start node position.
55+
56+
3. Use `end ` to keep track each group end node position
57+
58+
4. Reverse(`k nodes`)AKA: `[start.next, end]`.
59+
60+
5. After reverse, update `start` point to reversed group last node. and `end` point to `start` next node(`end=start.next`).
61+
62+
6. If `counts % k != 0`, then `end` move to next(`end=end.next`), for each move`count+1`.
63+
64+
For example(as below pic),`head=[1,2,3,4,5,6,7,8], k = 3`
65+
66+
67+
![reverse k nodes in linked list](../assets/problems/25.reverse-nodes-in-k-groups-2.PNG)
68+
69+
70+
>**NOTE**: Usually we create a `dummy node` to solve linked list problem, because head node may be changed during operation.
71+
for example: here `head updated from 1->3`, and `dummy (List(0)) ` keep the same.
72+
73+
#### Complexity Analysis
74+
- *Time Complexity:* `O(n) - n is number of Linked List`
75+
- *Space Complexity:* `O(1)`
76+
77+
## Key Points
78+
1. create a dummy node, `dummy = ListNode(0)`
79+
2. Group linked list as `k=3`, keep track of start and end node for each group.
80+
3. Reverse each group, update start and end node references
81+
4. return `dummy.next`.
82+
83+
## Code (`Java/Python3`)
84+
*Java Code*
85+
```java
86+
class ReverseKGroupsLinkedList {
87+
public ListNode reverseKGroup(ListNode head, int k) {
88+
if (head == null || k == 1) {
89+
return head;
90+
}
91+
ListNode dummy = new ListNode(0);
92+
dummy.next = head;
93+
94+
ListNode start = dummy;
95+
ListNode end = head;
96+
int count = 0;
97+
while (end != null) {
98+
count++;
99+
// group
100+
if (count % k == 0) {
101+
// reverse linked list (start, end]
102+
start = reverse(start, end.next);
103+
end = start.next;
104+
} else {
105+
end = end.next;
106+
}
107+
}
108+
return dummy.next;
109+
}
110+
111+
// reverse linked list from range (start, end], return last node.
112+
private ListNode reverse(ListNode pre, ListNode next) {
113+
ListNode last = pre.next;
114+
ListNode curr = last.next;
115+
116+
while (curr != next) {
117+
last.next = curr.next;
118+
curr.next = pre.next;
119+
pre.next = curr;
120+
curr = last.next;
121+
}
122+
return last;
123+
}
124+
}
125+
```
126+
127+
*Python3 Cose*
128+
```python
129+
class Solution:
130+
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
131+
if head is None or k < 2:
132+
return head
133+
dummy = ListNode(0)
134+
dummy.next = head
135+
start = dummy
136+
end = head
137+
count = 0
138+
while end:
139+
count += 1
140+
if count % k == 0:
141+
start = self.reverse(start, end.next)
142+
end = start.next
143+
else:
144+
end = end.next
145+
return dummy.next
146+
147+
def reverse(self, start, end):
148+
last = start.next
149+
curr = last.next
150+
while curr != end:
151+
last.next = curr.next
152+
curr.next = start.next
153+
start.next = curr
154+
curr = last.next
155+
return last
156+
```
157+
158+
## References
159+
- [Leetcode Discussion (yellowstone)](https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11440/Non-recursive-Java-solution-and-idea)
160+
161+
## Extension
162+
163+
- Require from right to left reverse nodes in k groups. **(ByteDance Interview)**
164+
165+
Example,`1->2->3->4->5->6->7->8, k = 3`,
166+
167+
From right to left, group as `k=3`:
168+
- `6->7->8` reverse to `8->7->6`
169+
- `3->4->5` reverse to `5->4->3`.
170+
- `1->2` only has 2 nodes, which less than `k=3`, do nothing.
171+
172+
return: `1->2->5->4->3->8->7->6`
173+
174+
Here, we pre-process linked list, reverse it first, then using Reverse nodes in K groups solution:
175+
176+
1. Reverse linked list
177+
178+
2. From left to right, reverse linked list group as k nodes.
179+
180+
3. Reverse step #2 linked list
181+
182+
For example:`1->2->3->4->5->6->7->8, k = 3`
183+
184+
1. Reverse linked list: `8->7->6->5->4->3->2->1`
185+
186+
2. Reverse nodes in k groups: `6->7->8->3->4->5->2->1`
187+
188+
3. Reverse step#2 linked list: `1->2->5->4->3->8->7->6`
189+
190+
## Similar Problems
191+
- [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/)

0 commit comments

Comments
 (0)