forked from azl397985856/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
lucifer
committed
Sep 23, 2020
1 parent
afc1994
commit 8cdd655
Showing
6 changed files
with
205 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
# 题目地址(面试题 17.12. BiNode) | ||
|
||
https://leetcode-cn.com/problems/binode-lcci/ | ||
|
||
## 题目描述 | ||
|
||
``` | ||
二叉树数据结构TreeNode可用来表示单向链表(其中left置空,right为下一个链表节点)。实现一个方法,把二叉搜索树转换为单向链表,要求依然符合二叉搜索树的性质,转换操作应是原址的,也就是在原始的二叉搜索树上直接修改。 | ||
返回转换后的单向链表的头节点。 | ||
注意:本题相对原题稍作改动 | ||
示例: | ||
输入: [4,2,5,1,3,null,6,0] | ||
输出: [0,null,1,null,2,null,3,null,4,null,5,null,6] | ||
提示: | ||
节点数量不会超过 100000。 | ||
``` | ||
|
||
## 前置知识 | ||
|
||
- 二叉查找树 | ||
- 递归 | ||
- [二叉树的遍历](../thinkings/binary-tree-traversal.md) | ||
|
||
## 公司 | ||
|
||
- 暂无 | ||
|
||
## 思路 | ||
|
||
实际上这就是一个考察二叉树遍历 + 二叉查找树性质的题目。需要注意的是指针操作,这一点和链表反转系列题目是一样的。 | ||
|
||
首先我们要知道一个性质: 对于一个二叉查找树来说,其中序遍历结果是一个有序数组。 而题目要求你输出的恰好就是有序数组(虽然没有明说, 不过从测试用例也可以看出)。 | ||
|
||
因此一个思路就是中序遍历, 边遍历边改变指针即可。 这里有两个注意点: | ||
|
||
1. 指针操作小心死循环 | ||
2. 你需要返回的是最左下角的节点,而不是题目给的 root | ||
|
||
对于第一个问题, 其实只要注意操作指针的顺序即可。对于第二个问题,我用了一个黑科技,让代码看起来简洁又高效。如果不懂的话, 你也可以换个朴素的写法。 | ||
|
||
让我们进入正题。 | ||
|
||
其中绿色是我们要增加的连线,而黑色是是原本的连线。 | ||
|
||
 | ||
|
||
我们再来看一个复杂一点的: | ||
|
||
 | ||
|
||
实际上,不管多么复杂。 我们只需要进行一次**中序遍历**,同时记录前驱节点。然后操作修改前驱节点和当前节点的指针即可,整个过程就好像是链表反转。 | ||
|
||
核心代码(假设 pre 我们已经正确计算出了): | ||
|
||
```py | ||
cur.left = None | ||
pre.right = cur | ||
pre = cur | ||
``` | ||
|
||
剩下的就是如何计算 pre,这个也不难,直接看代码: | ||
|
||
```py | ||
self.pre = None | ||
def dfs(root): | ||
dfs(root.left) | ||
# 上面的指针改变逻辑写到这里 | ||
self.pre = root | ||
dfs(root.right) | ||
|
||
``` | ||
|
||
问题得以解决。 | ||
|
||
这里还有最后一个问题就是返回值,题目要返回的实际上是最左下角的值。而我用了一个黑科技的方法(注意看注释): | ||
|
||
```py | ||
self.pre = self.ans = TreeNode(-1) | ||
def dfs(root): | ||
if not root: return | ||
dfs(root.left) | ||
root.left = None | ||
self.pre.right = root | ||
# 当第一次执行到下面这一行代码,恰好是在最左下角, 这个时候 self.pre = root 就切断了 self.pre 和 self.ans 的联系 | ||
# 之后 self.pre 的变化都不会体现到 self.ans 上。 | ||
# 直观上来说就是 self.ans 在遍历到最左下角的时候下车了 | ||
# 因此最后返回 self.ans 即可 | ||
self.pre = root | ||
dfs(root.right) | ||
dfs(root) | ||
return self.ans.right | ||
``` | ||
|
||
## 关键点 | ||
|
||
- 指针操作 | ||
- 返回值的处理 | ||
|
||
## 代码 | ||
|
||
```py | ||
class Solution: | ||
def convertBiNode(self, root): | ||
self.pre = self.ans = TreeNode(-1) | ||
def dfs(root): | ||
if not root: return | ||
dfs(root.left) | ||
root.left = None | ||
self.pre.right = root | ||
self.pre = root | ||
dfs(root.right) | ||
dfs(root) | ||
return self.ans.right | ||
|
||
``` | ||
|
||
**复杂度分析** | ||
|
||
- 时间复杂度:$O(N)$,其中 N 为树的节点总数。 | ||
- 空间复杂度:$O(h)$,其中 h 为树的高度。 | ||
|
||
## 相关题目 | ||
|
||
- [206.reverse-linked-list](./206.reverse-linked-list.md) | ||
- [92.reverse-linked-list-ii](./92.reverse-linked-list-ii.md) | ||
- [25.reverse-nodes-in-k-groups-cn](./25.reverse-nodes-in-k-groups-cn.md) | ||
|
||
## 扩展 | ||
|
||
大家也可以关注我的公众号《脑洞前端》获取更多更新鲜的 LeetCode 题解 | ||
|
||
 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Install the python extension for VS Code | ||
# (https:#marketplace.visualstudio.com/items?itemName=ms-python.python). | ||
|
||
# The Debug Visualizer has no support for Python data extractors yet, | ||
# so to visualize data, your value must be a valid JSON string representing the data. | ||
# See readme for supported data schemas. | ||
|
||
from json import dumps | ||
from random import randint | ||
|
||
graph = { | ||
"kind": {"graph": True}, | ||
"nodes": [ | ||
{"id": "1", "label": "1"} | ||
], | ||
"edges": [] | ||
} | ||
|
||
for i in range(2, 100): | ||
# add a node | ||
id = str(i) | ||
graph["nodes"].append({"id": id, "label": id}) | ||
# connects the node to a random edge | ||
targetId = str(randint(1, i - 1)) | ||
graph["edges"].append({"from": id, "to": targetId}) | ||
json_graph = dumps(graph) | ||
print("i is " + str(i)) | ||
# try setting a breakpoint right above | ||
# then put json_graph into the visualization console and press enter | ||
# when you step through the code each time you hit the breakpoint | ||
# the graph should automatically refresh! | ||
|
||
# example of json_graph visualization with 10 nodes: | ||
# https://i.imgur.com/RqZuYHH.png | ||
|
||
print("finished") |