Skip to content

Commit

Permalink
feat: binode-lcci
Browse files Browse the repository at this point in the history
  • Loading branch information
lucifer committed Sep 23, 2020
1 parent afc1994 commit 8cdd655
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 21 deletions.
6 changes: 6 additions & 0 deletions .vscode/launch.json
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"
}
2 changes: 2 additions & 0 deletions collections/easy.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- [binode-lcci](../problems/binode-lcci.md) 🆕

- [0001.two-sum](../problems/1.two-sum.md)
- [0020.Valid Parentheses](../problems/20.valid-parentheses.md)
- [0021.MergeTwoSortedLists](../problems/21.merge-two-sorted-lists.md)
Expand Down
139 changes: 139 additions & 0 deletions problems/binode-lcci.md
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

对于第一个问题, 其实只要注意操作指针的顺序即可。对于第二个问题,我用了一个黑科技,让代码看起来简洁又高效。如果不懂的话, 你也可以换个朴素的写法。

让我们进入正题。

其中绿色是我们要增加的连线,而黑色是是原本的连线。

![](https://tva1.sinaimg.cn/large/007S8ZIlly1gj0zk657mmj30qq0doabd.jpg)

我们再来看一个复杂一点的:

![](https://tva1.sinaimg.cn/large/007S8ZIlly1gj0zl95r69j31040m6tbc.jpg)

实际上,不管多么复杂。 我们只需要进行一次**中序遍历**,同时记录前驱节点。然后操作修改前驱节点和当前节点的指针即可,整个过程就好像是链表反转。

核心代码(假设 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 题解

![](https://tva1.sinaimg.cn/large/007S8ZIlly1ghluc9tkv6j30x20iwjtf.jpg)
38 changes: 20 additions & 18 deletions todo/candidates/215.kth-largest-element-in-an-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,28 @@
* @return {number}
*/
function maxHeapify(nums) {
nums.unshift(null);
for (let i = nums.length - 1; i >> 1 > 0; i--) {
// 自下往上堆化
if (nums[i] > nums[i >> 1]) { // 如果子元素更大,则交换位置
const temp = nums[i];
nums[i] = nums[i >> 1];
nums[i >> 1] = temp;
}
nums.unshift(null);

for (let i = nums.length - 1; i >> 1 > 0; i--) {
// 自下往上堆化
if (nums[i] > nums[i >> 1]) {
// 如果子元素更大,则交换位置
const temp = nums[i];
nums[i] = nums[i >> 1];
nums[i >> 1] = temp;
}
}
nums.shift();
return nums[0];
}
var findKthLargest = function (nums, k) {
// heap klogn
let ret = null;
for (let i = 0; i < k; i++) {
ret = maxHeapify(nums);
nums.shift();
return nums[0];
}
var findKthLargest = function(nums, k) {
// heap klogn
let ret = null;
for(let i = 0; i < k; i++) {
ret = maxHeapify(nums);
nums.shift();
}
return ret;
return ret;
};

findKthLargest([1, 2, 3, 4, 5], 2);
5 changes: 2 additions & 3 deletions todo/candidates/64.minimum-path-sum.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
* @param {number[][]} grid
* @return {number}
*/
var minPathSum = function(grid) {
// 时间复杂度和空间复杂度都是 O (m * n);
var minPathSum = function (grid) {
// 时间复杂度和空间复杂度都是 O (m * n);
if (grid.length === 0) return 0;
const dp = [];
const rows = grid.length;
Expand Down Expand Up @@ -39,4 +39,3 @@ var minPathSum = function(grid) {

return dp[rows][cols];
};

36 changes: 36 additions & 0 deletions todo/candidates/good-array.py
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")

0 comments on commit 8cdd655

Please sign in to comment.