自刷代码随想录Day13

对称二叉树

lc101. 对称二叉树(简单)

给你一个二叉树的根节点 root , 检查它是否轴对称。

在这里插入图片描述

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null) 
            return true;
        return compare(root.left, root.right);
    }

    public boolean compare(TreeNode left, TreeNode right) {
        // 首先排除两个结点不满足情况
        if (left == null && right != null) 
            return false;
        else if (left != null && right == null) 
            return false;
        else if (left == null && right == null) 
            return true;
        else if (left.val != right.val) 
            return false;
        
        // 此时就是开始递归子树了
        boolean outside = compare(left.left, right.right);
        boolean inside = compare(left.right, right.left);
        return outside && inside;
    }
}

该题方法挺多的,本次使用的是递归法,我们需要特别注意的是,对称不是所有结点的左右子节点都对称,而是根节点的左右子树对称,意思是我们需要比较两棵树的对称。

  1. 递归的起点是根节点的左右子节点,然后递归的结束条件就是有且只有一个结点为空(不对称),或者都不为空但是两个结点的值不一样(不对称),这两返回false;或者是两个结点都为null,此时就是对称的,返回true。
  2. 递归体:首先我们的左子树的左节点和右子树的右节点作比较,相同返回true,不同返回false;然后左子树的右节点和右子树的左节点作比较,相同返回true,不同返回false;当且仅当上面两个比较的返回值都为true时,该递归体里返回true。------ 这里需要理解的是,一旦有某个递归体返回了false,那么该递归体前面的都会false,结果false。

二叉树最大深度

lc104. 二叉树的最大深度(简单)

给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。

在这里插入图片描述

class Solution {
    public int maxDepth(TreeNode root) {
        return getDepth(root);
    }

    public int getDepth(TreeNode root) {
        if (root == null) 
            return 0;
        int lhight = getDepth(root.left);
        int rhight = getDepth(root.right);
        return Math.max(lhight, rhight) + 1;
    }
}

递归法,比较简单的一道题,通过看代码理解。


二叉树的最小深度

lc111. 二叉树的最小深度(简单)

class Solution {
    public int minDepth(TreeNode root) {
        return getMinDepth(root);
    }

    public int getMinDepth(TreeNode root) {
        if (root == null) 
            return 0;
        int lhight = getMinDepth(root.left);
        int rhight = getMinDepth(root.right);
        if ( lhight == 0 || rhight == 0) {
            return Math.max(lhight, rhight) + 1;
        }
        return Math.min(lhight, rhight) + 1;
    }
}

最小深度和最大深度思路是差不多的,但是二叉树的特殊性,需要特殊考虑结点存在高度为0的子树。比如某节点。如果他的左子树为空,右子树高度为n,那么这棵子树的最小高度不能以0为标准,而需要以存在子树的部分为标准。------ 首先得有子树才能考虑子树的高度。


二叉树的所有路径

lc257. 二叉树的所有路径

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。

在这里插入图片描述

class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> res = new ArrayList<>();
        if (root == null) 
            return res;
        List<Integer> paths = new ArrayList<>();
        traversal(root, paths, res);
        return res;
    }
    public void traversal(TreeNode root, List<Integer> paths, List<String> res ) {
        paths.add(root.val);
        // 遇到叶子节点
        if (root.left == null && root.right == null) {
            StringBuffer sb = new StringBuffer();// StringBuilder用来拼接字符串,速度更快
            for (int i = 0; i < paths.size() - 1; i++) {
                sb.append(paths.get(i)).append("->");
            }
            sb.append(paths.get(paths.size() - 1));// 记录最后一个节点
            res.add(sb.toString());
            return ;
        }
        // 递归和回溯是同时进行,所以要放在同一个花括号里
        if (root.left != null) {
            traversal(root.left, paths, res);
            paths.remove(paths.size() - 1);
        }
        if (root.right != null) {
            traversal(root.right, paths, res);
            paths.remove(paths.size() - 1);
        }
    }
}

该题的定性是简单,但是我觉得还是挺难的,因为思路还是比较绕的,又涉及到了回溯、字符串拼接。
此题使用的方法主要还是递归法,因为需要路径,所以选择前序遍历。
该题的思路就是遇见叶子结点,就将路径中的元素拼成一个String放进res中,如果不是叶子节点就进去咯,但是进去后出来的时候需要删除该结点在paths中的路径,这就是回溯。

路径总和

lc112. 路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。

在这里插入图片描述
在这里插入图片描述

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null)
            return false;
        targetSum -= root.val;
        if (root.left == null && root.right == null) {
            return targetSum == 0;
        }
        if (root.left != null) {
            boolean left = hasPathSum(root.left, targetSum);
            if (left) {
                return true;
            }
        }
        if (root.right != null) {
            boolean right = hasPathSum(root.right, targetSum);
            if (right) {
                return true;
            }
        }
        return false;
    }
}

该题和上一题的思路可以说是如出一辙,但是这个解法是换了一种表达方式。
这道题我们需要学习的是boolean变量在递归中怎么一步一步的传递 ----- 非常重要。


路径总和 II

lc113. 路径总和 II(中等)

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。

在这里插入图片描述
在这里插入图片描述

class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null)
            return res;
        List<Integer> paths = new ArrayList<>();
        Traversal(root, targetSum, res, paths);
        return res;
    }
    public void Traversal(TreeNode cur, int targetSum, List<List<Integer>> res, List<Integer> paths) {
        paths.add(cur.val);
        if (cur.left == null && cur.right == null) {
            // 找到了和为 targetsum 的路径
            if (targetSum - cur.val == 0) {
                res.add(new ArrayList<>(paths));
            }
            return ;
        }
        if (cur.left != null) {
            Traversal(cur.left, targetSum - cur.val, res, paths);
            paths.remove(paths.size() - 1);
        }
        if (cur.right != null) {
            Traversal(cur.right, targetSum - cur.val, res, paths);
            paths.remove(paths.size() - 1);
        }
    }
}

这道题比上面两道题与求所有路径和更像,但是奇怪的是,我们的targetSum 始终只能递减,直到为0停止,而不能使用sum = 0然后累加到targetSum 时来验证结果的正确性,这个我还是没有理解到为什么。
ArrayList的性质可以看一下,用数组挨着存储,取值是顺序取出,也就是可以根据索引取值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值