Skip to content

Commit 863d586

Browse files
committed
116
1 parent 1022b68 commit 863d586

File tree

4 files changed

+145
-4
lines changed

4 files changed

+145
-4
lines changed

SUMMARY.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
* [99. Recover Binary Search Tree](leetcode-99-Recover-Binary-Search-Tree.md)
103103
* [100. Same Tree](leetcode-100-Same-Tree.md)
104104
* [leetcode 100 斩!回顾](leetcode100斩回顾.md)
105-
* [101 题到 115](leetcode-101-200.md)
105+
* [101 题到 116](leetcode-101-200.md)
106106
* [101. Symmetric Tree](leetcode-101-Symmetric-Tree.md)
107107
* [102. Binary Tree Level Order Traversal](leetcode-102-Binary-Tree-Level-Order-Traversal.md)
108108
* [103. Binary Tree Zigzag Level Order Traversal](leetcode-103-Binary-Tree-Zigzag-Level-Order-Traversal.md)
@@ -117,4 +117,5 @@
117117
* [112. Path Sum](leetcode-112-Path-Sum.md)
118118
* [113. Path Sum II](leetcode-113-Path-SumII.md)
119119
* [114. Flatten Binary Tree to Linked List](leetcode-114-Flatten-Binary-Tree-to-Linked-List.md)
120-
* [115*. Distinct Subsequences](leetcode-115-Distinct-Subsequences.md)
120+
* [115*. Distinct Subsequences](leetcode-115-Distinct-Subsequences.md)
121+
* [116. Populating Next Right Pointers in Each Node](leetcode-116-Populating-Next-Right-Pointers-in-Each-Node.md)

leetcode-101-200.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@
2626

2727
<a href="leetcode-114-Flatten-Binary-Tree-to-Linked-List.html">114. Flatten Binary Tree to Linked List</a>
2828

29-
<a href="leetcode-115-Distinct-Subsequences.html">115. Distinct Subsequences</a>
29+
<a href="leetcode-115-Distinct-Subsequences.html">115. Distinct Subsequences</a>
30+
31+
<a href="leetcode-116-Populating-Next-Right-Pointers-in-Each-Node.html">116. Populating Next Right Pointers in Each Node</a>

leetcode-115-Distinct-Subsequences.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ private int numDistinctHelper(String s, int s_start, String t, int t_start) {
102102

103103
![](https://windliang.oss-cn-beijing.aliyuncs.com/115_2.jpg)
104104

105-
原因就是因为递归函数中,我们多次调用了递归函数,这会使得我们重复递归很多的过程,解决方案就很简单了,`Memoization ` 技术,把每次的结果利用一个`map`保存起来,再求之前,先看`map`中有没有,有的话直接拿出来就可以了。
105+
原因就是因为递归函数中,我们多次调用了递归函数,这会使得我们重复递归很多的过程,解决方案就很简单了,`Memoization ` 技术,把每次的结果利用一个`map`保存起来,在求之前,先看`map`中有没有,有的话直接拿出来就可以了。
106106

107107
`map``key`的话就标识当前的递归,`s_start``t_start` 联合表示,利用字符串 `s_start + '@' + t_start`
108108

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# 题目描述(中等难度)
2+
3+
![](https://windliang.oss-cn-beijing.aliyuncs.com/116.jpg)
4+
5+
![](https://windliang.oss-cn-beijing.aliyuncs.com/116_2.jpg)
6+
7+
给定一个满二叉树,每个节点多了一个`next`指针,然后将所有的`next`指针指向它的右边的节点。并且要求空间复杂度是`O(1)`
8+
9+
# 解法一 BFS
10+
11+
如果没有要求空间复杂度这道题就简单多了,我们只需要用一个队列做`BFS``BFS`参见 [102 题](<https://leetcode.wang/leetcode-102-Binary-Tree-Level-Order-Traversal.html>)。然后按顺序将每个节点连起来就可以了。
12+
13+
```java
14+
public Node connect(Node root) {
15+
if (root == null) {
16+
return root;
17+
}
18+
Queue<Node> queue = new LinkedList<Node>();
19+
queue.offer(root);
20+
while (!queue.isEmpty()) {
21+
int size = queue.size();
22+
Node pre = null;
23+
for (int i = 0; i < size; i++) {
24+
Node cur = queue.poll();
25+
//从第二个节点开始,将前一个节点的 pre 指向当前节点
26+
if (i > 0) {
27+
pre.next = cur;
28+
}
29+
pre = cur;
30+
if (cur.left != null) {
31+
queue.offer(cur.left);
32+
}
33+
if (cur.right != null) {
34+
queue.offer(cur.right);
35+
}
36+
37+
}
38+
}
39+
return root;
40+
}
41+
```
42+
43+
# 解法二 迭代
44+
45+
当然既然题目要求了空间复杂度,那么我们来考虑下不用队列该怎么处理。只需要解决三个问题就够了。
46+
47+
* 每一层怎么遍历?
48+
49+
之前是用队列将下一层的节点保存了起来。
50+
51+
这里的话,其实只需要提前把下一层的`next`构造完成,到了下一层的时候就可以遍历了。
52+
53+
* 什么时候进入下一层?
54+
55+
之前是得到当前队列的元素个数,然后遍历那么多次。
56+
57+
这里的话,注意到最右边的节点的`next``null`,所以可以判断当前遍历的节点是不是`null`
58+
59+
* 怎么得到每层开头节点?
60+
61+
之前队列把当前层的所以节点存了起来,得到开头节点当然很容易。
62+
63+
这里的话,我们额外需要一个变量把它存起来。
64+
65+
三个问题都解决了,就可以写代码了。利用三个指针,`start` 指向每层的开始节点,`cur`指向当前遍历的节点,`pre`指向当前遍历的节点的前一个节点。
66+
67+
![](https://windliang.oss-cn-beijing.aliyuncs.com/116_3.jpg)
68+
69+
如上图,我们需要把 `pre` 的左孩子的 `next` 指向右孩子,`pre` 的右孩子的`next`指向`cur`的左孩子。
70+
71+
![](https://windliang.oss-cn-beijing.aliyuncs.com/116_4.jpg)
72+
73+
如上图,当 `cur` 指向 `null` 以后,我们只需要把 `pre` 的左孩子的 `next` 指向右孩子。
74+
75+
```java
76+
public Node connect(Node root) {
77+
if (root == null) {
78+
return root;
79+
}
80+
Node pre = root;
81+
Node cur = null;
82+
Node start = pre;
83+
while (pre.left != null) {
84+
//遍历到了最右边的节点,要将 pre 和 cur 更新到下一层,并且用 start 记录
85+
if (cur == null) {
86+
//我们只需要把 pre 的左孩子的 next 指向右孩子。
87+
pre.left.next = pre.right;
88+
89+
pre = start.left;
90+
cur = start.right;
91+
start = pre;
92+
//将下一层的 next 连起来,同时 pre、next 后移
93+
} else {
94+
//把 pre 的左孩子的 next 指向右孩子
95+
pre.left.next = pre.right;
96+
//pre 的右孩子的 next 指向 cur 的左孩子。
97+
pre.right.next = cur.left;
98+
99+
pre = pre.next;
100+
cur = cur.next;
101+
}
102+
}
103+
return root;
104+
}
105+
```
106+
107+
分享下 `leetcode` 的高票回答的代码,看起来更简洁一些,`C++` 写的。
108+
109+
```C++
110+
void connect(TreeLinkNode *root) {
111+
if (root == NULL) return;
112+
TreeLinkNode *pre = root;
113+
TreeLinkNode *cur = NULL;
114+
while(pre->left) {
115+
cur = pre;
116+
while(cur) {
117+
cur->left->next = cur->right;
118+
if(cur->next) cur->right->next = cur->next->left;
119+
cur = cur->next;
120+
}
121+
pre = pre->left;
122+
}
123+
}
124+
```
125+
126+
我的代码里的变量和他的变量对应关系如下。
127+
128+
```java
129+
我的 start pre cur
130+
| | |
131+
他的 pre cur cur.next
132+
```
133+
134+
除了变量名不一样,算法本质还是一样的。
135+
136+
#
137+
138+
题目让我们初始化 `next` 指针,初始化过程中我们又利用到了`next`指针,很巧妙了。

0 commit comments

Comments
 (0)