Skip to content

Commit 0c37f70

Browse files
committed
25 K个一组翻转链表
Signed-off-by: subond <yubc0321@gmail.com>
1 parent 48ce4de commit 0c37f70

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
## 25 K个一组翻转链表-困难
2+
3+
题目:
4+
5+
给你链表的头节点 `head` ,每 `k` 个节点一组进行翻转,请你返回修改后的链表。
6+
7+
`k` 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 `k` 的整数倍,那么请将最后剩余的节点保持原有顺序。
8+
9+
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
10+
11+
12+
13+
> **示例 1:**
14+
>
15+
> ![img](https://assets.leetcode.com/uploads/2020/10/03/reverse_ex1.jpg)
16+
>
17+
> ```
18+
> 输入:head = [1,2,3,4,5], k = 2
19+
> 输出:[2,1,4,3,5]
20+
> ```
21+
>
22+
> **示例 2:**
23+
>
24+
> ![img](https://assets.leetcode.com/uploads/2020/10/03/reverse_ex2.jpg)
25+
>
26+
> ```
27+
> 输入:head = [1,2,3,4,5], k = 3
28+
> 输出:[3,2,1,4,5]
29+
> ```
30+
31+
32+
33+
**解题思路**
34+
35+
这道题可以递归翻转,具体为:
36+
37+
1. 先实现一个区间翻转的函数,满足K个直接进入区间翻转
38+
2. 不足 k 个直接返回
39+
40+
```go
41+
// date 2024/01/11
42+
/**
43+
* Definition for singly-linked list.
44+
* type ListNode struct {
45+
* Val int
46+
* Next *ListNode
47+
* }
48+
*/
49+
func reverseKGroup(head *ListNode, k int) *ListNode {
50+
node := head
51+
for i := 0; i < k; i++ {
52+
if node == nil {
53+
return head
54+
}
55+
node = node.Next
56+
}
57+
newHead := reverse(head, node) // reverse 之后 head.Next = node
58+
head.Next = reverseKGroup(node, k)
59+
return newHead
60+
}
61+
62+
// reverse [first, last) then return new head
63+
// not contains the last node
64+
func reverse(first, last *ListNode) *ListNode {
65+
prev := last
66+
for first != last {
67+
tmp := first.Next
68+
first.Next = prev
69+
prev = first
70+
first = tmp
71+
}
72+
return prev
73+
}
74+
```
75+
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
## 426 将二叉搜索树转化为排序后的双向链表-中等
2+
3+
题目:
4+
5+
将一个 **二叉搜索树** 就地转化为一个 **已排序的双向循环链表**
6+
7+
对于双向循环列表,你可以将左右孩子指针作为双向循环链表的前驱和后继指针,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
8+
9+
特别地,我们希望可以 **就地** 完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中最小元素的指针。
10+
11+
12+
13+
> **示例 1:**
14+
>
15+
> ```
16+
> 输入:root = [4,2,5,1,3]
17+
>
18+
>
19+
> 输出:[1,2,3,4,5]
20+
>
21+
> 解释:下图显示了转化后的二叉搜索树,实线表示后继关系,虚线表示前驱关系。
22+
> ```
23+
>
24+
> **示例 2:**
25+
>
26+
> ```
27+
> 输入:root = [2,1,3]
28+
> 输出:[1,2,3]
29+
> ```
30+
>
31+
> **示例 3:**
32+
>
33+
> ```
34+
> 输入:root = []
35+
> 输出:[]
36+
> 解释:输入是空树,所以输出也是空链表。
37+
> ```
38+
>
39+
> **示例 4:**
40+
>
41+
> ```
42+
> 输入:root = [1]
43+
> 输出:[1]
44+
> ```
45+
46+
47+
48+
**解题思路**
49+
50+
根据访问根节点的顺序不同,树有三种遍历方式,前序、中序和后序。这道题给出的是二叉搜索树,而且要求给出排序的双向链表,那么递归版中序更合适。
51+
52+
因为递归中序遍历的时候,可以最先达到值最小的那个节点,把它保存为 first。
53+
54+
同时,第一个点也是 last 节点。然后递归遍历,将节点依次追加到 last 即可。
55+
56+
最后,再把 last 的后继指向 first,first 的前驱指向 last。
57+
58+
```go
59+
// date 2024/01/11
60+
/**
61+
* Definition for a Node.
62+
* type Node struct {
63+
* Val int
64+
* Left *Node
65+
* Right *Node
66+
* }
67+
*/
68+
69+
func treeToDoublyList(root *Node) *Node {
70+
if root == nil {
71+
return root
72+
}
73+
var first, last *Node
74+
75+
var inorder func(root *Node)
76+
inorder = func(root *Node) {
77+
if root == nil {
78+
return
79+
}
80+
inorder(root.Left)
81+
if last != nil {
82+
last.Right = root
83+
root.Left = last
84+
} else {
85+
// last == nil
86+
// this is first
87+
first = root
88+
}
89+
// save root
90+
last = root
91+
inorder(root.Right)
92+
}
93+
inorder(root)
94+
last.Right = first
95+
first.Left = last
96+
return first
97+
}
98+
```
99+

0 commit comments

Comments
 (0)