Skip to content

Commit 09555d1

Browse files
author
lucifer
committed
feat: binode-lcci
1 parent ec41023 commit 09555d1

File tree

6 files changed

+205
-21
lines changed

6 files changed

+205
-21
lines changed

.vscode/launch.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0"
6+
}

collections/easy.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
- [binode-lcci](../problems/binode-lcci.md) 🆕
2+
13
- [0001.two-sum](../problems/1.two-sum.md)
24
- [0020.Valid Parentheses](../problems/20.valid-parentheses.md)
35
- [0021.MergeTwoSortedLists](../problems/21.merge-two-sorted-lists.md)

problems/binode-lcci.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# 题目地址(面试题 17.12. BiNode)
2+
3+
https://leetcode-cn.com/problems/binode-lcci/
4+
5+
## 题目描述
6+
7+
```
8+
二叉树数据结构TreeNode可用来表示单向链表(其中left置空,right为下一个链表节点)。实现一个方法,把二叉搜索树转换为单向链表,要求依然符合二叉搜索树的性质,转换操作应是原址的,也就是在原始的二叉搜索树上直接修改。
9+
10+
返回转换后的单向链表的头节点。
11+
12+
注意:本题相对原题稍作改动
13+
14+
 
15+
16+
示例:
17+
18+
输入: [4,2,5,1,3,null,6,0]
19+
输出: [0,null,1,null,2,null,3,null,4,null,5,null,6]
20+
提示:
21+
22+
节点数量不会超过 100000。
23+
```
24+
25+
## 前置知识
26+
27+
- 二叉查找树
28+
- 递归
29+
- [二叉树的遍历](../thinkings/binary-tree-traversal.md)
30+
31+
## 公司
32+
33+
- 暂无
34+
35+
## 思路
36+
37+
实际上这就是一个考察二叉树遍历 + 二叉查找树性质的题目。需要注意的是指针操作,这一点和链表反转系列题目是一样的。
38+
39+
首先我们要知道一个性质: 对于一个二叉查找树来说,其中序遍历结果是一个有序数组。 而题目要求你输出的恰好就是有序数组(虽然没有明说, 不过从测试用例也可以看出)。
40+
41+
因此一个思路就是中序遍历, 边遍历边改变指针即可。 这里有两个注意点:
42+
43+
1. 指针操作小心死循环
44+
2. 你需要返回的是最左下角的节点,而不是题目给的 root
45+
46+
对于第一个问题, 其实只要注意操作指针的顺序即可。对于第二个问题,我用了一个黑科技,让代码看起来简洁又高效。如果不懂的话, 你也可以换个朴素的写法。
47+
48+
让我们进入正题。
49+
50+
其中绿色是我们要增加的连线,而黑色是是原本的连线。
51+
52+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gj0zk657mmj30qq0doabd.jpg)
53+
54+
我们再来看一个复杂一点的:
55+
56+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gj0zl95r69j31040m6tbc.jpg)
57+
58+
实际上,不管多么复杂。 我们只需要进行一次**中序遍历**,同时记录前驱节点。然后操作修改前驱节点和当前节点的指针即可,整个过程就好像是链表反转。
59+
60+
核心代码(假设 pre 我们已经正确计算出了):
61+
62+
```py
63+
cur.left = None
64+
pre.right = cur
65+
pre = cur
66+
```
67+
68+
剩下的就是如何计算 pre,这个也不难,直接看代码:
69+
70+
```py
71+
self.pre = None
72+
def dfs(root):
73+
dfs(root.left)
74+
# 上面的指针改变逻辑写到这里
75+
self.pre = root
76+
dfs(root.right)
77+
78+
```
79+
80+
问题得以解决。
81+
82+
这里还有最后一个问题就是返回值,题目要返回的实际上是最左下角的值。而我用了一个黑科技的方法(注意看注释):
83+
84+
```py
85+
self.pre = self.ans = TreeNode(-1)
86+
def dfs(root):
87+
if not root: return
88+
dfs(root.left)
89+
root.left = None
90+
self.pre.right = root
91+
# 当第一次执行到下面这一行代码,恰好是在最左下角, 这个时候 self.pre = root 就切断了 self.pre 和 self.ans 的联系
92+
# 之后 self.pre 的变化都不会体现到 self.ans 上。
93+
# 直观上来说就是 self.ans 在遍历到最左下角的时候下车了
94+
# 因此最后返回 self.ans 即可
95+
self.pre = root
96+
dfs(root.right)
97+
dfs(root)
98+
return self.ans.right
99+
```
100+
101+
## 关键点
102+
103+
- 指针操作
104+
- 返回值的处理
105+
106+
## 代码
107+
108+
```py
109+
class Solution:
110+
def convertBiNode(self, root):
111+
self.pre = self.ans = TreeNode(-1)
112+
def dfs(root):
113+
if not root: return
114+
dfs(root.left)
115+
root.left = None
116+
self.pre.right = root
117+
self.pre = root
118+
dfs(root.right)
119+
dfs(root)
120+
return self.ans.right
121+
122+
```
123+
124+
**复杂度分析**
125+
126+
- 时间复杂度:$O(N)$,其中 N 为树的节点总数。
127+
- 空间复杂度:$O(h)$,其中 h 为树的高度。
128+
129+
## 相关题目
130+
131+
- [206.reverse-linked-list](./206.reverse-linked-list.md)
132+
- [92.reverse-linked-list-ii](./92.reverse-linked-list-ii.md)
133+
- [25.reverse-nodes-in-k-groups-cn](./25.reverse-nodes-in-k-groups-cn.md)
134+
135+
## 扩展
136+
137+
大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的 LeetCode 题解
138+
139+
![](https://tva1.sinaimg.cn/large/007S8ZIlly1ghluc9tkv6j30x20iwjtf.jpg)

todo/candidates/215.kth-largest-element-in-an-array.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,28 @@
99
* @return {number}
1010
*/
1111
function maxHeapify(nums) {
12-
nums.unshift(null);
13-
14-
for (let i = nums.length - 1; i >> 1 > 0; i--) {
15-
// 自下往上堆化
16-
if (nums[i] > nums[i >> 1]) { // 如果子元素更大,则交换位置
17-
const temp = nums[i];
18-
nums[i] = nums[i >> 1];
19-
nums[i >> 1] = temp;
20-
}
12+
nums.unshift(null);
13+
14+
for (let i = nums.length - 1; i >> 1 > 0; i--) {
15+
// 自下往上堆化
16+
if (nums[i] > nums[i >> 1]) {
17+
// 如果子元素更大,则交换位置
18+
const temp = nums[i];
19+
nums[i] = nums[i >> 1];
20+
nums[i >> 1] = temp;
2121
}
22+
}
23+
nums.shift();
24+
return nums[0];
25+
}
26+
var findKthLargest = function (nums, k) {
27+
// heap klogn
28+
let ret = null;
29+
for (let i = 0; i < k; i++) {
30+
ret = maxHeapify(nums);
2231
nums.shift();
23-
return nums[0];
2432
}
25-
var findKthLargest = function(nums, k) {
26-
// heap klogn
27-
let ret = null;
28-
for(let i = 0; i < k; i++) {
29-
ret = maxHeapify(nums);
30-
nums.shift();
31-
}
32-
return ret;
33+
return ret;
3334
};
3435

36+
findKthLargest([1, 2, 3, 4, 5], 2);

todo/candidates/64.minimum-path-sum.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
* @param {number[][]} grid
88
* @return {number}
99
*/
10-
var minPathSum = function(grid) {
11-
// 时间复杂度和空间复杂度都是 O (m * n);
10+
var minPathSum = function (grid) {
11+
// 时间复杂度和空间复杂度都是 O (m * n);
1212
if (grid.length === 0) return 0;
1313
const dp = [];
1414
const rows = grid.length;
@@ -39,4 +39,3 @@ var minPathSum = function(grid) {
3939

4040
return dp[rows][cols];
4141
};
42-

todo/candidates/good-array.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Install the python extension for VS Code
2+
# (https:#marketplace.visualstudio.com/items?itemName=ms-python.python).
3+
4+
# The Debug Visualizer has no support for Python data extractors yet,
5+
# so to visualize data, your value must be a valid JSON string representing the data.
6+
# See readme for supported data schemas.
7+
8+
from json import dumps
9+
from random import randint
10+
11+
graph = {
12+
"kind": {"graph": True},
13+
"nodes": [
14+
{"id": "1", "label": "1"}
15+
],
16+
"edges": []
17+
}
18+
19+
for i in range(2, 100):
20+
# add a node
21+
id = str(i)
22+
graph["nodes"].append({"id": id, "label": id})
23+
# connects the node to a random edge
24+
targetId = str(randint(1, i - 1))
25+
graph["edges"].append({"from": id, "to": targetId})
26+
json_graph = dumps(graph)
27+
print("i is " + str(i))
28+
# try setting a breakpoint right above
29+
# then put json_graph into the visualization console and press enter
30+
# when you step through the code each time you hit the breakpoint
31+
# the graph should automatically refresh!
32+
33+
# example of json_graph visualization with 10 nodes:
34+
# https://i.imgur.com/RqZuYHH.png
35+
36+
print("finished")

0 commit comments

Comments
 (0)