Skip to content
  • Sponsor azl397985856/leetcode

  • Notifications You must be signed in to change notification settings
  • Fork 9.5k
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3e6a534

Browse files
snowanazl397985856
authored andcommittedSep 3, 2019
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

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
Loading
Lines changed: 207 additions & 0 deletions
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/)
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
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, end) - start and end exclusively`.
59+
60+
5. After reverse, update `start` point to reversed group last node.
61+
62+
6. If `counts % k != 0`, then `end` move to next(`end=end.next`), for each move`count+1`.
63+
64+
As below pic show steps 4 and 5, reverse linked list in range `(start, end)`:
65+
66+
![reverse linked list range in (start, end)](../assets/problems/25.reverse-nodes-in-k-groups-3.png)
67+
68+
69+
For example(as below pic),`head=[1,2,3,4,5,6,7,8], k = 3`
70+
71+
72+
![reverse k nodes in linked list](../assets/problems/25.reverse-nodes-in-k-groups-2.PNG)
73+
74+
75+
>**NOTE**: Usually we create a `dummy node` to solve linked list problem, because head node may be changed during operation.
76+
for example: here `head updated from 1->3`, and `dummy (List(0)) ` keep the same.
77+
78+
#### Complexity Analysis
79+
- *Time Complexity:* `O(n) - n is number of Linked List`
80+
- *Space Complexity:* `O(1)`
81+
82+
## Key Points
83+
1. create a dummy node, `dummy = ListNode(0)`
84+
2. Group linked list as `k=3`, keep track of start and end node for each group.
85+
3. Reverse each group, update start and end node references
86+
4. return `dummy.next`.
87+
88+
## Code (`Java/Python3`)
89+
*Java Code*
90+
```java
91+
class ReverseKGroupsLinkedList {
92+
public ListNode reverseKGroup(ListNode head, int k) {
93+
if (head == null || k == 1) {
94+
return head;
95+
}
96+
ListNode dummy = new ListNode(0);
97+
dummy.next = head;
98+
99+
ListNode start = dummy;
100+
ListNode end = head;
101+
int count = 0;
102+
while (end != null) {
103+
count++;
104+
// group
105+
if (count % k == 0) {
106+
// reverse linked list (start, end]
107+
start = reverse(start, end.next);
108+
end = start.next;
109+
} else {
110+
end = end.next;
111+
}
112+
}
113+
return dummy.next;
114+
}
115+
116+
/**
117+
* reverse linked list from range (start, end), return last node.
118+
* for example:
119+
* 0->1->2->3->4->5->6->7->8
120+
* | |
121+
* start end
122+
*
123+
* After call start = reverse(start, end)
124+
*
125+
* 0->3->2->1->4->5->6->7->8
126+
* | |
127+
* start end
128+
*
129+
* @return the reversed list's 'start' node, which is the precedence of node end
130+
*/
131+
private ListNode reverse(ListNode start, ListNode end) {
132+
ListNode curr = start.next;
133+
ListNode prev = start;
134+
ListNode first = curr;
135+
while (curr != end){
136+
ListNode temp = curr.next;
137+
curr.next = prev;
138+
prev = curr;
139+
curr = temp;
140+
}
141+
start.next = prev;
142+
first.next = curr;
143+
return first;
144+
}
145+
}
146+
```
147+
148+
*Python3 Cose*
149+
```python
150+
class Solution:
151+
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
152+
if head is None or k < 2:
153+
return head
154+
dummy = ListNode(0)
155+
dummy.next = head
156+
start = dummy
157+
end = head
158+
count = 0
159+
while end:
160+
count += 1
161+
if count % k == 0:
162+
start = self.reverse(start, end.next)
163+
end = start.next
164+
else:
165+
end = end.next
166+
return dummy.next
167+
168+
def reverse(self, start, end):
169+
prev, curr = start, start.next
170+
first = curr
171+
while curr != end:
172+
temp = curr.next
173+
curr.next = prev
174+
prev = curr
175+
curr = temp
176+
start.next = prev
177+
first.next = curr
178+
return first
179+
```
180+
181+
## References
182+
- [Leetcode Discussion (yellowstone)](https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11440/Non-recursive-Java-solution-and-idea)
183+
184+
## Extension
185+
186+
- Require from right to left reverse nodes in k groups. **(ByteDance Interview)**
187+
188+
Example,`1->2->3->4->5->6->7->8, k = 3`,
189+
190+
From right to left, group as `k=3`:
191+
- `6->7->8` reverse to `8->7->6`
192+
- `3->4->5` reverse to `5->4->3`.
193+
- `1->2` only has 2 nodes, which less than `k=3`, do nothing.
194+
195+
return: `1->2->5->4->3->8->7->6`
196+
197+
Here, we pre-process linked list, reverse it first, then using Reverse nodes in K groups solution:
198+
199+
1. Reverse linked list
200+
201+
2. From left to right, reverse linked list group as k nodes.
202+
203+
3. Reverse step #2 linked list
204+
205+
For example:`1->2->3->4->5->6->7->8, k = 3`
206+
207+
1. Reverse linked list: `8->7->6->5->4->3->2->1`
208+
209+
2. Reverse nodes in k groups: `6->7->8->3->4->5->2->1`
210+
211+
3. Reverse step#2 linked list: `1->2->5->4->3->8->7->6`
212+
213+
## Similar Problems
214+
- [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/)

0 commit comments

Comments
 (0)
Please sign in to comment.