110.平衡二叉树
给定一个二叉树,判断它是否是 平衡二叉树
注:平衡二叉树指的是 它是一棵空树或它的左右两个子树的高度差的绝对值不超过1
这里注意二叉树 深度 与 高度 的区别
深度 从上到下求,前序遍历
高度 从下到上求,后序遍历
思路
递归方式
class Solution {
public boolean isBalanced(TreeNode root) {
int hight = judge(root);
if(hight == -1) return false;
return true;
}
//正常情况下返回当前节点的高度,-1表明已不是平衡二叉树
public int judge(TreeNode root){
if(root == null){
return 0;
}
int left = judge(root.left);
int right = judge(root.right);
if(right == -1 || left == -1) return -1;
// 左右子树高度差大于1,return -1表示已经不是平衡树了
if (Math.abs(left - right) > 1) {
return -1;
}
//注意运算符优先级 此处需加括号
return 1 + (left > right ? left : right);
}
}
总结
通过本题可以了解求二叉树深度 和 二叉树高度的差异,求深度适合用前序遍历,而求高度适合用后序遍历。
本题迭代法其实有点复杂,大家可以有一个思路,也不一定说非要写出来。
但是递归方式是一定要掌握的!
257. 二叉树的所有路径
给你一个二叉树的根节点 root
,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
思路
前序遍历 + 递归 + 回溯
递归过程中,每向下一个节点便将节点加入path 而后判断当前节点是否为叶子节点 是 则将path加入到res 否则进行递归,但要注意在递归后进行回溯
如下图所示
体现思维过程的解法:
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<Integer> path = new ArrayList<>();
List<String> res = new ArrayList<>();
path(root,path, res);
return res;
}
public void path(TreeNode root,List<Integer> path, List<String> res){
path.add(root.val);//中
//遇到了叶子节点
if(root.left == null && root.right == null){
StringBuilder sb = new StringBuilder();
for(int i=0; i < path.size() - 1; i++){
sb.append(Integer.toString(path.get(i)) + "->");
}
sb.append(path.get(path.size()-1));
res.add(sb.toString());
}
//左
if(root.left != null){
path(root.left, path, res);
path.remove(path.size() - 1);//回溯
}
//右
if(root.right != null){
path(root.right, path, res);
path.remove(path.size() - 1);//回溯
}
}
}
更精简的解法:
回溯隐藏在path(root.left, path + "->", result);
中的 path + "->"
。 每次函数调用完,path依然是没有加上"->" 的,这就是回溯了。
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
String path = "";
List<String> res = new ArrayList<>();
path(root,path, res);
return res;
}
public void path(TreeNode root,String path, List<String> res){
path += root.val;//中
//遇到了叶子节点
if(root.left == null && root.right == null){
res.add(path);
return;
}
//左
if(root.left != null){
path(root.left, path + "->", res);
}
//右
if(root.right != null){
path(root.right, path + "->", res);
}
}
}
如果把 path + "->"
作为函数参数就是可以的,因为并没有改变path的数值,执行完递归函数之后,path依然是之前的数值(相当于回溯了)
综合以上,第二种递归的代码虽然精简但把很多重要的点隐藏在了代码细节里,第一种递归写法虽然代码多一些,但是把每一个逻辑处理都完整的展现出来了。
404.左叶子之和
给定二叉树的根节点 root
,返回所有左叶子之和。
递归
递归 + 后序遍历 + 判断左叶子
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null) return 0;
return getLeftSum(root);
}
public int getLeftSum(TreeNode root){
if(root == null){
return 0;
}
//因为只有当前遍历节点为父节点,才能判断其子节点是不是左节点 所以叶子节点的左叶子和为0
if(root.left == null && root.right == null){
return 0;
}
int left = getLeftSum(root.left);
int right = getLeftSum(root.right);
int mid = 0;
//判断左叶子 对应左子树就是一个左叶子的情况
if(root.left != null && root.left.left == null && root.left.right == null){
mid = root.left.val;
}
return mid + left + right;
}
}
或者改变mid
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null) return 0;
return getLeftSum(root);
}
public int getLeftSum(TreeNode root){
if(root == null){
return 0;
}
//因为只有当前遍历节点为父节点,才能判断其子节点是不是左节点 所以叶子节点的左叶子和为0
if(root.left == null && root.right == null){
return 0;
}
int left = getLeftSum(root.left); //左
//判断左叶子 对应左子树就是一个左叶子的情况
if(root.left != null && root.left.left == null && root.left.right == null){
left = root.left.val;
}
int right = getLeftSum(root.right); // 右
return left + right;//中
}
}
迭代
只需要遍历每个节点 把左叶子节点统计出来,就可以了
所以dfs/bfs均可
dfs
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null){
return 0;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
int result = 0;
while(!stack.isEmpty()){
TreeNode t = stack.pop();
if(t.left != null && t.left.left == null && t.left.right == null){
result += t.left.val;
}
if(t.left != null) stack.push(t.left);
if(t.right != null) stack.push(t.right);
}
return result;
}
}
bfs
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null){
return 0;
}
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
int result = 0;
while(!que.isEmpty()){
TreeNode node = que.poll();
if(node.left != null && node.left.left == null && node.left.right == null){
result += node.left.val;
}
if(node.left != null) que.offer(node.left);
if(node.right != null) que.offer(node.right);
}
return result;
}
}