Skip to content

Add LC 25 reverse nodes in k group #156

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ The data structures mainly includes:

- [0004.median-of-two-sorted-array](./problems/4.median-of-two-sorted-array.md) 🆕
- [0023.merge-k-sorted-lists](./problems/23.merge-k-sorted-lists.md)
- [0025.reverse-nodes-in-k-group](./problems/25.reverse-nodes-in-k-groups-en.md) 🆕
- [0032.longest-valid-parentheses](./problems/32.longest-valid-parentheses.md) 🆕
- [0042.trapping-rain-water](./problems/42.trapping-rain-water.md)
- [0124.binary-tree-maximum-path-sum](./problems/124.binary-tree-maximum-path-sum.md)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。

- [0004.median-of-two-sorted-array](./problems/4.median-of-two-sorted-array.md) 🆕
- [0023.merge-k-sorted-lists](./problems/23.merge-k-sorted-lists.md)
- [0025.reverse-nodes-in-k-group](./problems/25.reverse-nodes-in-k-groups-cn.md) 🆕
- [0032.longest-valid-parentheses](./problems/32.longest-valid-parentheses.md) 🆕
- [0042.trapping-rain-water](./problems/42.trapping-rain-water.md)
- [0124.binary-tree-maximum-path-sum](./problems/124.binary-tree-maximum-path-sum.md)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
207 changes: 207 additions & 0 deletions problems/25.reverse-nodes-in-k-groups-cn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
## 题目地址
https://leetcode.com/problems/reverse-nodes-in-k-group/

## 题目描述
```
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

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.

Example:

Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

Note:

Only constant extra memory is allowed.
You may not alter the values in the list's nodes, only nodes itself may be changed.

```

## 思路
题意是以 `k` 个nodes为一组进行翻转,返回翻转后的`linked list`.

从左往右扫描一遍`linked list`,扫描过程中,以k为单位把数组分成若干段,对每一段进行翻转。给定首尾nodes,如何对链表进行翻转。

链表的翻转过程,初始化一个为`null `的 `previous node(prev)`,然后遍历链表的同时,当前`node (curr)`的下一个(next)指向前一个`node(prev)`,
在改变当前node的指向之前,用一个临时变量记录当前node的下一个`node(curr.next)`. 即
```
ListNode temp = curr.next;
curr.next = prev;
prev = curr;
curr = temp;
```

举例如图:翻转整个链表 `1->2->3->4->null` -> `4->3->2->1->null`

![reverse linked list](../assets/problems/25.reverse-nodes-in-k-groups-1.PNG)

这里是对每一组(`k个nodes`)进行翻转,

1. 先分组,用一个`count`变量记录当前节点的个数

2. 用一个`start` 变量记录当前分组的起始节点位置的前一个节点

3. 用一个`end `变量记录要翻转的最后一个节点位置

4. 翻转一组(`k个nodes`)即`(start, end) - start and end exclusively`。

5. 翻转后,`start`指向翻转后链表, 区间`(start,end)`中的最后一个节点, 返回`start` 节点。

6. 如果不需要翻转,`end` 就往后移动一个(`end=end.next`),每一次移动,都要`count+1`.

如图所示 步骤4和5: 翻转区间链表区间`(start, end)`

![reverse linked list range in (start, end)](../assets/problems/25.reverse-nodes-in-k-groups-3.png)


举例如图,`head=[1,2,3,4,5,6,7,8], k = 3`


![reverse k nodes in linked list](../assets/problems/25.reverse-nodes-in-k-groups-2.PNG)


>**NOTE**: 一般情况下对链表的操作,都有可能会引入一个新的`dummy node`,因为`head`有可能会改变。这里`head 从1->3`,
`dummy (List(0)) `保持不变。

#### 复杂度分析
- *时间复杂度:* `O(n) - n is number of Linked List`
- *空间复杂度:* `O(1)`

## 关键点分析
1. 创建一个dummy node
2. 对链表以k为单位进行分组,记录每一组的起始和最后节点位置
3. 对每一组进行翻转,更换起始和最后的位置
4. 返回`dummy.next`.

## 代码 (`Java/Python3`)
*Java Code*
```java
class ReverseKGroupsLinkedList {
public ListNode reverseKGroup(ListNode head, int k) {
if (head == null || k == 1) {
return head;
}
ListNode dummy = new ListNode(0);
dummy.next = head;

ListNode start = dummy;
ListNode end = head;
int count = 0;
while (end != null) {
count++;
// group
if (count % k == 0) {
// reverse linked list (start, end]
start = reverse(start, end.next);
end = start.next;
} else {
end = end.next;
}
}
return dummy.next;
}

/**
* reverse linked list from range (start, end), return last node.
* for example:
* 0->1->2->3->4->5->6->7->8
* | |
* start end
*
* After call start = reverse(start, end)
*
* 0->3->2->1->4->5->6->7->8
* | |
* start end
* first
*
*/
private ListNode reverse(ListNode start, ListNode end) {
ListNode curr = start.next;
ListNode prev = start;
ListNode first = curr;
while (curr != end){
ListNode temp = curr.next;
curr.next = prev;
prev = curr;
curr = temp;
}
start.next = prev;
first.next = curr;
return first;
}
}
```

*Python3 Cose*
```python
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
if head is None or k < 2:
return head
dummy = ListNode(0)
dummy.next = head
start = dummy
end = head
count = 0
while end:
count += 1
if count % k == 0:
start = self.reverse(start, end.next)
end = start.next
else:
end = end.next
return dummy.next

def reverse(self, start, end):
prev, curr = start, start.next
first = curr
while curr != end:
temp = curr.next
curr.next = prev
prev = curr
curr = temp
start.next = prev
first.next = curr
return first
```

## 参考(References)
- [Leetcode Discussion (yellowstone)](https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11440/Non-recursive-Java-solution-and-idea)

## 扩展

- 要求从后往前以`k`个为一组进行翻转。**(字节跳动(ByteDance)面试题)**

例子,`1->2->3->4->5->6->7->8, k = 3`,

从后往前以`k=3`为一组,
- `6->7->8` 为一组翻转为`8->7->6`,
- `3->4->5`为一组翻转为`5->4->3`.
- `1->2`只有2个nodes少于`k=3`个,不翻转。

最后返回: `1->2->5->4->3->8->7->6`

这里的思路跟从前往后以`k`个为一组进行翻转类似,可以进行预处理:

1. 翻转链表

2. 对翻转后的链表进行从前往后以k为一组翻转。

3. 翻转步骤2中得到的链表。

例子:`1->2->3->4->5->6->7->8, k = 3`

1. 翻转链表得到:`8->7->6->5->4->3->2->1`

2. 以k为一组翻转: `6->7->8->3->4->5->2->1`

3. 翻转步骤#2链表: `1->2->5->4->3->8->7->6`

## 类似题目
- [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/)
Loading