学习目标
- 练习二叉树相关题目递归法
学习内容
110. 平衡二叉树(Easy)
题目链接:110. 平衡二叉树
题目:给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:true
示例 2:
输入:root = [1,2,2,3,3,null,null,4,4]
输出:false
示例 3:
输入:root = []
输出:true
思路:一开始并没有思路, 这道题其实还是要拐弯的. 利用递归计算:
- 若当前节点为空, 返回0
- 后续遍历, 递归计算当前节点左子树高度和右子树高度
- 若左子树高度或右子树高度等于-1, 或 |左子树高度-右子树高度| > 1, 返回 -1;
- 若无上述情况, 返回 Max(左子树高度, 右子树高度) + 1;
- 最后比对递归计算的结果是否 == -1
时间复杂度:O(n)
空间复杂度:O(log n)
解决方案:
class Solution {
public boolean isBalanced(TreeNode root) {
return countBalanced(root) >= 0;
}
public int countBalanced(TreeNode root) {
if(root == null) return 0;
int left = countBalanced(root.left);
int right = countBalanced(root.right);
if(left == -1 || right == -1 || Math.abs(right - left) > 1) return -1;
return Math.max(left, right) + 1;
}
}
小结:递归法的前提是理解题目
257. 二叉树的所有路径(Easy)
题目链接:257. 二叉树的所有路径
题目:给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [1,2,3,null,5]
输出:[“1->2->5”,“1->3”]
示例 2:
输入:root = [1]
输出:[“1”]
思路:前序遍历
时间复杂度:O(n)
空间复杂度:O(log n)
解决方案:
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> ans = new ArrayList<>();
preOrder(ans, root, "");
return ans;
}
public void preOrder(List<String> list, TreeNode root, String path) {
if(root == null) return;
if(root.left == null && root.right == null) {
String s = path + root.val;
list.add(s);
return;
}
preOrder(list, root.left, path + root.val + "->");
preOrder(list, root.right, path + root.val + "->");
}
}
上面的写法会比较慢, 应该是直接用 String 拼接造成的.使用 StringBuilder 拼接可以加快速度:
class Solution {
List<String> ans = new ArrayList<>();
public List<String> binaryTreePaths(TreeNode root) {
preOrder(root, "");
return ans;
}
public void preOrder(TreeNode root, String path) {
if(root == null) return;
StringBuilder sb = new StringBuilder(path);
sb.append(root.val);
if(root.left == null && root.right == null) {
ans.add(sb.toString());
return;
}
sb.append("->");
preOrder(root.left, sb.toString());
preOrder(root.right, sb.toString());
}
}
小结:当需要字符串拼接时, 使用 StringBuilder 可以更快速.
404. 左叶子之和(Easy)
题目链接:404. 左叶子之和
题目:给定二叉树的根节点 root ,返回所有左叶子之和。
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:
输入: root = [1]
输出: 0
思路:只能想到
if(root.left != null && root.left.left == null && root.left.right == null) {
left = root.left.val;
}
但是没想到先int left = sumOfLeftLeaves(root.left);
时间复杂度:O(n)
空间复杂度:O(log n)
解决方案:
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null) return 0;
if(root.left == null && root.right == null) return 0;
int left = sumOfLeftLeaves(root.left);
if(root.left != null && root.left.left == null && root.left.right == null) {
left = root.left.val;
}
int right = sumOfLeftLeaves(root.right);
return left + right;
}
}
小结:感觉这是一种新形式的递归, Mark.
总结
当需要字符串拼接时, 使用 StringBuilder 可以更快速.
另外, 这几道题虽然都是 Easy, 但是都是没完整思路的题目, 还需增加广度.