【LeetCode】987. Vertical Order Traversal of a Binary Tree 解题报告(C++ & Python)
作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/
题目描述
Given a binary tree, return the vertical order traversal of its nodes values.
For each node at position (X, Y)
, its left and right children respectively will be at positions (X-1, Y-1)
and (X+1, Y-1)
.
Running a vertical line from X = -infinity
to X = +infinity
, whenever the vertical line touches some nodes, we report the values of the nodes in order from top to bottom (decreasing Y
coordinates).
If two nodes have the same position, then the value of the node that is reported first is the value that is smaller.
Return an list of non-empty reports in order of X
coordinate. Every report will have a list of values of nodes.
Example 1:
Input: [3,9,20,null,null,15,7]
Output: [[9],[3,15],[20],[7]]
Explanation:
Without loss of generality, we can assume the root node is at position (0, 0):
Then, the node with value 9 occurs at position (-1, -1);
The nodes with values 3 and 15 occur at positions (0, 0) and (0, -2);
The node with value 20 occurs at position (1, -1);
The node with value 7 occurs at position (2, -2).
Example 2:
Input: [1,2,3,4,5,6,7]
Output: [[4],[2],[1,5,6],[3],[7]]
Explanation:
The node with value 5 and the node with value 6 have the same position according to the given scheme.
However, in the report "[1,5,6]", the node value of 5 comes first since 5 is smaller than 6.
Note:
- The tree will have between
1
and1000
nodes. - Each node’s value will be between
0
and1000
.
题目大意
一个二叉树从左到右竖着看,每列的结果放到一起,那么结果是什么样的。
规定:一个节点水平方向的位置是X,竖直方向的高度是Y,其坐标是(X, Y)
。那么其左右孩子的坐标分别是(X-1, Y-1)
and (X+1, Y-1)
.
即要求把相同X的节点位置放在一起,并且要求结果中节点的存放是从上到下的。如果两个节点的坐标相同,那么value小的节点排列在前面。
解题方法
DFS
最直白的方法就是把每个节点的位置给求出来,然后构建出题目要求的排列方式。为了方便,我们在求的过程中就把相同X值的放到一起,同时保存Y坐标和值。
所以定义了一个Map,这个Map的结构是map<int, vector<pair<int, int>>>,保存的是x ==> (-y, value)的映射。所以在进行DFS的过程中,我们会给每个坐标都记录下其坐标(X,Y),然后我们根据其坐标把相同X的都放到一起。为什么使用-y呢?这是因为题目中告诉我们节点的Y坐标更小,而题目要求的Y排序是顺序是从上到下的。如果设置根节点层的Y坐标是0的话,那么下面各层的真实Y值应该是-1,-2,-3……,我们的sort函数默认是递增排序的,所以为了sort方便,放到vector中的是-y。
在求出相同X的所有(-y, value)对之后,我们进行了排序使得Y值是严格递增的,当Y值相同时按照value值进行排序。然后把排序好了的节点的value值都取出来放到结果里即可。
一个不引起注意的点是,nodeMap一定要使用map数据结构,而不是unordered_map。因为map会保证有序的,也就是说对nodeMap遍历的时候,X是已经排序好了。而unordered_map是无序结构,遍历不会保证X是有序,增加了麻烦。
另外一个C++的知识点是当使用 for (auto nm : nodeMap)
的时候,nm不是一个指针,而是一个复制了的对象,所以不要使用nm->second
,而应该使用nm.second
.
时间复杂度是O(N + N*(N*log(N) + N))。第一个N是DFS要把每个节点进行遍历一次;for循环有层N,循环里面有层排序是NlogN,遍历是N)。
空间复杂度是O(N)。
C++代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
nodeMap.clear();
dfs(root, 0, 0);
vector<vector<int>> res;
for (auto nm : nodeMap) {
sort(nm.second.begin(), nm.second.end());
vector<int> cols;
for (auto p : nm.second)
cols.push_back(p.second);
res.push_back(cols);
}
return res;
}
private:
map<int, vector<pair<int, int>>> nodeMap; // x ==> (-y, value)
void dfs(TreeNode* root, int x, int y) {
if (!root) return;
nodeMap[x].emplace_back(-y, root->val);
dfs(root->left, x - 1, y - 1);
dfs(root->right, x + 1, y - 1);
}
};
下面的python代码没有使用字典,而是使用了list保存了(x, -y, value)三元组的方式,可以直接使用sort进行排序。这样带来的麻烦是需要使用比较前后两个相邻的三元组对应的x值是否相等来判断是否放到同一个列的list中,代码如下:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def verticalTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
self.m_ = list()
self.dfs(root, 0, 0)
self.m_.sort()
res = [[self.m_[0][2]]]
for i in range(1, len(self.m_)):
if self.m_[i][0] == self.m_[i - 1][0]:
res[-1].append(self.m_[i][2])
else:
res.append([self.m_[i][2]])
return res
def dfs(self, root, x, y):
if not root: return
self.m_.append((x, -y, root.val))
self.dfs(root.left, x - 1, y - 1)
self.dfs(root.right, x + 1, y - 1)
BFS
这个题同样也可以使用BFS来解决,通过维护一个队列,我们从上到下依次遍历每个节点,给每个节点设置好了坐标。这个队列存储的是个三元组(TreeNode*,int x,int y)做法和DFS的方法极其类似,就不再详细讲了。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
queue<pair<TreeNode*, pair<int, int>>> q; // node, x, y
q.push(make_pair(root, make_pair(0, 0)));
map<int, vector<pair<int, int>>> nodeMap;
while (!q.empty()) {
auto d = q.front(); q.pop();
TreeNode* curNode = d.first;
int x = d.second.first;
int y = d.second.second;
nodeMap[x].emplace_back(-y, curNode->val);
if (curNode->left)
q.push(make_pair(curNode->left, make_pair(x - 1, y - 1)));
if (curNode->right)
q.push(make_pair(curNode->right, make_pair(x + 1, y - 1)));
}
vector<vector<int>> res;
for (auto nm : nodeMap) {
sort(nm.second.begin(), nm.second.end());
vector<int> cols;
for (auto p : nm.second)
cols.push_back(p.second);
res.push_back(cols);
}
return res;
}
};
python版本的BFS如下,同样是先把所有的节点遍历一遍并保存每个节点的位置,然后根据位置再排序遍历求解的方式做到的。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def verticalTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
q = collections.deque()
q.append((root, 0, 0))
m_ = list()
while q:
node, x, y = q.popleft()
m_.append((x, -y, node.val))
if node.left:
q.append((node.left, x - 1, y - 1))
if node.right:
q.append((node.right, x + 1, y - 1))
m_.sort()
res = [[m_[0][2]]]
for i in range(1, len(m_)):
if m_[i][0] == m_[i - 1][0]:
res[-1].append(m_[i][2])
else:
res.append([m_[i][2]])
return res
日期
2019 年 2 月 20 日 —— 少刷知乎多做题
【LeetCode】987. Vertical Order Traversal of a Binary Tree 解题报告(C++ & Python)的更多相关文章
- LeetCode 987. Vertical Order Traversal of a Binary Tree
原题链接在这里:https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/ 题目: Given a binary ...
- 【leetcode】987. Vertical Order Traversal of a Binary Tree
题目如下: Given a binary tree, return the vertical order traversal of its nodes values. For each node at ...
- LC 987. Vertical Order Traversal of a Binary Tree
Given a binary tree, return the vertical order traversal of its nodes values. For each node at posit ...
- 【LeetCode】958. Check Completeness of a Binary Tree 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 BFS DFS 日期 题目地址:https://le ...
- 【LeetCode】637. Average of Levels in Binary Tree 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:DFS 方法二:BFS 日期 题目地址:ht ...
- 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)
[LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...
- 【LeetCode】331. Verify Preorder Serialization of a Binary Tree 解题报告(Python)
[LeetCode]331. Verify Preorder Serialization of a Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https:/ ...
- 【LeetCode】297. Serialize and Deserialize Binary Tree 解题报告(Python)
[LeetCode]297. Serialize and Deserialize Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode ...
- 【LeetCode】662. Maximum Width of Binary Tree 解题报告(Python)
[LeetCode]662. Maximum Width of Binary Tree 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.co ...
随机推荐
- fatal error: runtime: out of memory
[root@VM_0_10_centos frp_0.27.0_linux_amd64]# top top - 21:09:19 up 2 days, 4 min, 2 users, load ave ...
- centos 7的命令变化
1.service -> systemctl命令 2.ifconfig -> ip 命令 3.netstat -> ss命令 4.route -> ip route命令 5.t ...
- CSS3实现字体描边
CSS3实现字体描边的两种方法 -webkit-text-stroke: 1px #fff;:不建议,向内描边,字体颜色变细,效果不佳: 用box-shadow模拟描边,向外描边,保留字体粗细,赞! ...
- aboard, abolish
aboard board做动词有上车/船/飞机的意思,boarding就是正在上.board做名词有板的意思,车厢地板的板. a是个词根,有三种意思:1. 以某种状态或方式,如: ablaze, af ...
- pow()是如何实现的?
如1.5 ** 2.5,如何计算?似乎是这样的: 1. cmath calculates pow(a,b) by performing exp(b * log(a)). stackoverflow 2 ...
- Linux磁盘分区(一)之fdisk命令
Linux磁盘分区(一)之fdisk命令转自:https://www.cnblogs.com/machangwei-8/p/10353683.html 一.fdisk 的介绍fdsik 能划分磁盘成为 ...
- 转Android service 启动篇之 startForegroundService
本文转自:https://blog.csdn.net/shift_wwx/article/details/82496447 前言: 在官方文档 Android 8.0 行为变更 中有这样一段话: An ...
- 【Service】【Database】【MySQL】基础概念
1. 数据模型:层次模型.网状模型.关系模型 关系模型: 二维关系: 表:row, column 索引:index 视图:view 2. SQL接口:Structured Query Language ...
- 1945-祖安 say hello-String
1 #define _CRT_SECURE_NO_WARNINGS 1 2 #include<bits/stdc++.h> 3 char str[100][40]; 4 char s[10 ...
- 常用windows命令和Dos命令
Windows常用快捷键 Ctrl + C :复制 Ctrl + V :粘贴 Ctrl + X :剪切 Ctrl + A :全选 Ctrl + Z :撤销(做错了后退一步) Ctrl + Y :向前一 ...