【LeetCode】655. Print Binary Tree 解题报告(Python & C++)
作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/print-binary-tree/description/
题目描述
Print a binary tree in an m*n 2D string array following these rules:
- The row number m should be equal to the height of the given binary tree.
- The column number n should always be an odd number.
- The root node’s value (in string format) should be put in the exactly middle of the first row it can be put. The column and the row where the root node belongs will separate the rest space into two parts (left-bottom part and right-bottom part). You should print the left subtree in the left-bottom part and print the right subtree in the right-bottom part. The left-bottom part and the right-bottom part should have the same size. Even if one subtree is none while the other is not, you don’t need to print anything for the none subtree but still need to leave the space as large as that for the other subtree. However, if two subtrees are none, then you don’t need to leave space for both of them.
- Each unused space should contain an empty string “”.
- Print the subtrees following the same rules.
Example 1:
Input:
1
/
2
Output:
[["", "1", ""],
["2", "", ""]]
Example 2:
Input:
1
/ \
2 3
\
4
Output:
[["", "", "", "1", "", "", ""],
["", "2", "", "", "", "3", ""],
["", "", "4", "", "", "", ""]]
Example 3:
Input:
1
/ \
2 5
/
3
/
4
Output:
[["", "", "", "", "", "", "", "1", "", "", "", "", "", "", ""]
["", "", "", "2", "", "", "", "", "", "", "", "5", "", "", ""]
["", "3", "", "", "", "", "", "", "", "", "", "", "", "", ""]
["4", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]]
Note: The height of binary tree is in the range of [1, 10].
题目大意
使用二维数组打印出二叉树。如果某个位置是空节点,也应该给它留出对应的位置。
解题方法
DFS
最初认为,给空节点留下位置加大了题目难度。其实真正理解题目要考察的内容之后,发现这个条件让我们可以使用完全二叉树
的数学公式,所以使题目变得简单了。
这个题首先要求出树的高度,然后求出完全二叉树的宽度。根据高度和宽度构建出二维数组,再利用递归求出每个层次的每个节点对应的二维数组的位置,设为节点的值即可。
如果是DFS去做的话,每次向下搜索的时候,需要传入这个子区间的起始位置。根节点放在中间。
说的容易,难的再求这些公式,真的就是完全二叉树的一些知识。具体的就看这两篇文章吧,很详细。
代码:
# 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 printTree(self, root):
"""
:type root: TreeNode
:rtype: List[List[str]]
"""
if not root: return [""]
def getDepth(root):
if not root:
return 0
return 1 + max(getDepth(root.left), getDepth(root.right))
d = getDepth(root)
cols = 2 ** d - 1
self.res = [["" for i in range(cols)] for j in range(d)]
def helper(root, d, pos):
self.res[-d - 1][pos] = str(root.val)
if root.left: helper(root.left, d - 1, pos - 2 ** (d - 1))
if root.right: helper(root.right, d - 1, pos + 2 ** (d - 1))
helper(root, d - 1, 2 ** (d - 1) - 1)
return self.res
上面的python代码不够直观,如果使用类似二分查找的方式,使用left和right表示左右区间,那么代码可以写成下面这样。
/**
* 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<string>> printTree(TreeNode* root) {
const int h = depth(root);
int w = pow(2, h) - 1;
vector<vector<string>> res(h, vector<string>(w, ""));
dfs(root, res, 0, 0, w);
return res;
}
private:
int depth(TreeNode* root) {
if (!root) return 0;
return max(depth(root->left), depth(root->right)) + 1;
}
// [left, right)
void dfs(TreeNode* root, vector<vector<string>>& res, int depth, int left, int right) {
if (!root || depth == res.size()) return;
int mid = left + (right - left) / 2;
res[depth][mid] = to_string(root->val);
dfs(root->left, res, depth + 1, left, mid);
dfs(root->right, res, depth + 1, mid + 1, right);
}
};
BFS
使用BFS的话,就是类似于层次遍历的解法。这个题困难的地方在于不好找出节点要放置的位置。所以使用了两个BFS,一个BFS用来遍历节点,另一个BFS用来保存每个节点对应的起始位置。每次把根节点放到中间的地方,也就有点类似于二分查找。
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<string>> printTree(TreeNode* root) {
const int h = depth(root);
int w = pow(2, h) - 1;
int curH = -1;
vector<vector<string>> res(h, vector<string>(w, ""));
queue<TreeNode*> q;
q.push(root);
// [first, second)
queue<pair<int, int>> idxQ;
idxQ.push({0, w});
while (!q.empty()) {
curH++;
int size = q.size();
for (int i = 0; i < size; i++) {
TreeNode* node = q.front(); q.pop();
auto idx = idxQ.front(); idxQ.pop();
if (!node) continue;
int left = idx.first, right = idx.second;
int mid = left + (right - left) / 2;
res[curH][mid] = to_string(node->val);
q.push(node->left);
q.push(node->right);
idxQ.push({left, mid});
idxQ.push({mid + 1, right});
}
}
return res;
}
private:
int depth(TreeNode* root) {
if (!root) return 0;
return max(depth(root->left), depth(root->right)) + 1;
}
};
上面需要同时维护两个队列,其实可以使用一个队列,这个队列同时维护了该节点以及该节点所在的区间的左右位置。而在BFS中是不用维护当前的高度的,BFS可以存储当前属于哪一层。
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<string>> printTree(TreeNode* root) {
int d = depth(root);
int w = (1 << d) - 1;
queue<pair<TreeNode*, pair<int, int>>> q; // TreeNode*, start, end
q.push({root, {0, w}});
vector<vector<string>> res(d, vector<string>(w));
int curd = 0;
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; ++i) {
auto f = q.front(); q.pop();
TreeNode* node = f.first;
int start = f.second.first;
int end = f.second.second;
if (!node) continue;
int mid = start + (end - start) / 2;
res[curd][mid] = to_string(node->val);
q.push({node->left, {start, mid - 1}});
q.push({node->right, {mid + 1, end}});
}
++curd;
}
return res;
}
int depth(TreeNode* root) {
if (!root) return 0;
return max(depth(root->left), depth(root->right)) + 1;
}
};
日期
2018 年 3 月 4 日
2018 年 12 月 18 日 —— 改革开放40周年
2019 年 2 月 25 日 —— 二月就要完了
【LeetCode】655. Print Binary Tree 解题报告(Python & C++)的更多相关文章
- 【LeetCode】654. Maximum Binary Tree 解题报告 (Python&C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcode ...
- [LeetCode] 655. Print Binary Tree 打印二叉树
Print a binary tree in an m*n 2D string array following these rules: The row number m should be equa ...
- LeetCode 226 Invert Binary Tree 解题报告
题目要求 Invert a binary tree. 题目分析及思路 给定一棵二叉树,要求每一层的结点逆序.可以使用递归的思想将左右子树互换. python代码 # Definition for a ...
- LeetCode 965 Univalued Binary Tree 解题报告
题目要求 A binary tree is univalued if every node in the tree has the same value. Return true if and onl ...
- LeetCode 655. Print Binary Tree (C++)
题目: Print a binary tree in an m*n 2D string array following these rules: The row number m should be ...
- 【LeetCode】Balanced Binary Tree 解题报告
[题目] Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced bi ...
- 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)
[LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...
- 【LeetCode】297. Serialize and Deserialize Binary Tree 解题报告(Python)
[LeetCode]297. Serialize and Deserialize Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode ...
- 【LeetCode】331. Verify Preorder Serialization of a Binary Tree 解题报告(Python)
[LeetCode]331. Verify Preorder Serialization of a Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https:/ ...
随机推荐
- linux安全性增加
账户安全问题 Linux 默认会安装很多不必要的用户和用户组,如果不需要某些用户或者组,就要立即删除它,因为账户越多,系统就越不安全,很可能被黑客利用,进而威胁到服务器的安全. Linux系统中可以 ...
- (亿级流量)分布式防重复提交token设计
大型互联网项目中,很多流量都达到亿级.同一时间很多的人在使用,而每个用户提交表单的时候都可能会出现重复点击的情况,此时如果不做好控制,那么系统将会产生很多的数据重复的问题.怎样去设计一个高可用的防重复 ...
- 学习java 7.12
学习内容: File是文件和目录路径名的抽象表示,File封装的不是一个真正存在的文件,仅仅是一个路径名 File类的方法 绝对目录和相对目录的区别 字节流 使用字节输出流写数据的步骤 : 创建字节输 ...
- day31 协程
day31 协程 一.死锁与递归锁 所谓死锁:是指两个或者两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产 ...
- 03-Collection用例管理及批量执行
当我们对一个或多个系统中的很多用例进行维护时,首先想到的就是对用例进行分类管理,同时还希望对这批用例做回归测试 .在postman也提供了这样一个功能,就是Collection .通过这个Collec ...
- ubantu打开摄像头失败
摘要-针对ubantu20 sudo apt install v4l-utils v4l2-ctl --list-devices - cv2 install on ubantu20```针对ubant ...
- 转 GSON
转 https://www.jianshu.com/p/75a50aa0cad1 GSON弥补了JSON的许多不足的地方,在实际应用中更加适用于Java开发.在这里,我们主要讲解的是利用GSON来操作 ...
- 【Java 调优】Java性能优化
Java性能优化的50个细节(珍藏版) 1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: ...
- CSS font-size: 0去除内联元素空白间隙
我们在编写HTML标签的时候,通常会使用换行,缩进来保证代码的可读性.同时,在编写CSS样式的时候,也会需要把一些元素设置为inline或inline-block.这样一来,有时在页面中会出现意外的空 ...
- shiro免认证的路径配置
– ?:匹配一个字符,如/admin? 将匹配/admin1,但不匹配/admin 或/admin/:– *:匹配零个或多个字符串,如/admin 将匹配/admin./admin123,但不匹配/a ...