LeetCode经典算法题目二(树、排序、查找、动态规划、回溯、贪心)

LeetCode经典算法题目一(字符串、数组、链表、栈、队列、哈希)

六、树

1. 相同的树

树结点类:

public class TreeNode {
   
	int val;    //结点值
    TreeNode left;   //左结点
    TreeNode right;    //右结点
    TreeNode(int x) {
    val = x; }
}

算法: 递归。每次比较两个树的当前结点的值,可分四种情况:

  1. 结点均为空 √
  2. 一个为空一个不为空 ×
  3. 均不为空且结点值相同 √
  4. 均不为空但结点值不同 ×

其中,若为第三种情况就要再比较它们的子树是否相同,即把当前结点的左右子结点再作为参数传递,最后返回左右子树分别比较后相与的结果值。(意思是:必须满足左右子树全部都走通了,没有一个过程返回值为false,最终结果才能返回true)

class Solution {
   
    public boolean isSameTree(TreeNode p, TreeNode q) {
   
        if(p==null && q==null)
            return true;
        if(p==null || q==null)
            return false;
        if(p.val == q.val) 
            return (isSameTree(p.left,q.left) && isSameTree(p.right,q.right));
        return false;
    }
}

2. 对称二叉树

算法一: 递归。在同一个类中再写一个比较两树结点的方法,递归调用该方法,每次比较两子树对应结点值。(此题与上一题的区别: 上一题是两棵树进行横向比较;本题是只有一棵树进行内部比较,但使用递归方法我需要把一棵树拆成两棵来比较,方法是:拷贝根结点)这样一来算法思想就跟上题一样,分为四种情况:

  1. 结点均为空 √
  2. 一个为空一个不为空 ×
  3. 均不为空且结点值相同 √
  4. 均不为空但结点值不同 ×

其中,若为第三种情况就要再比较它们的子树是否对称相同,即把左右结点作为参数传递,最终返回比较后相与的结果值。
注意: 本题跟上题在返回结果处有本质区别,本题由于树是对称的,所以比较的是左结点的左结点右结点的右结点看是否相同。“左”、“右”进行比较,若相同才叫对称。

class Solution {
   
    public boolean isSymmetric(TreeNode root) {
   
        return compare(root,root);
    }
    public boolean compare(TreeNode l,TreeNode r){
   
        if(l==null && r==null)   //情况1
            return true;
        if(l==null || r==null)    //情况2
            return false;
        if(l.val == r.val){
        //情况3
            return compare(l.left,r.right)&&compare(l.right,r.left);
        }
        return false;    //情况4
    }
}

算法二: 迭代
(待完善)

3. 二叉树的最大深度(★)

算法: 深度优先算法(递归实现)

class Solution {
   
    public int maxDepth(TreeNode root) {
   
        if(root==null)
            return 0;
        int l_len = maxDepth(root.left);
        int r_len = maxDepth(root.right);
        return Math.max(l_len,r_len)+1;
    }
}

4. 将有序数组转换为二叉搜索树

二叉搜索树是指:或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

题目描述:将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
算法: 递归。每一次执行递归方法都返回一个根结点。根结点的值是数组最中间的元素。这样一来数组就被中间元素拆成左右两个数组,分别作为根结点的左右子树。

length 0 1 2 3 4 ……
n=length/2 / 0 0 1 2 ……
有无左右子树? / 无子树 有左子树 有左子树、右子树 有左子树、右子树 有左子树、右子树

注意: 要判断三种情况:

  1. 如果数组长度为0,那么就没有树结点了,直接返回null
  2. 判断数组长度是否大于1,因为只有大于1才会有左子树,否则不用进行查找左右子树
  3. 数组长度大于1之后还需要判断数组长度是否大于2,因为只有大于2才会出现右子树
class Solution {
   
    public TreeNode sortedArrayToBST(int[] nums) {
   
        if(nums.length == 0)   //情况1,数组长度为0,返回空
            return null;
        int m = nums.length/2;
        int n = nums[m];
        TreeNode root = new TreeNode(n);
        if(nums.length>1){
      //情况2,数组长度大于1,有左子树
            int[] num1 = new int[m];
            if(nums.length>2){
       //情况3,数组长度大于2,有右子树
                int[] num2 = new int[nums.length-m-1];
                System.arraycopy(nums,m+1,num2,0,nums.length-m-1);   //利用数组拷贝方法将数组拆分成左右两个
                root.right = sortedArrayToBST(num2);
            }
            System.arraycopy(nums,0,num1,0,m);
            root.left = sortedArrayToBST(num1);
        }
        return root;   //返回根结点
    }
}

5. 平衡二叉树

题目描述:给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

ps:由于本题没有要求需要为二叉搜索树,所以只用考虑子树高度差这一个方面。
算法一: 递归+递归。该类中的两个方法分别都进行递归,其中:

  • 第一个方法:递归地判断每个结点的左右子树高度差的绝对值是否不超过1;
  • 第二个方法:查询每个结点的深度

第一个方法在递归的时候会调用第二个方法,连起来就是:每一次拿到一个结点,会出现三种情况:

  1. 如果结点为空直接返回true,满足平衡二叉树要求
  2. 结点不为空的话我就去计算它的左右子树分别的高度(即深度),于是调用第二个方法(即第3题求二叉树深度的方法)。如果两个子树高度差的绝对值大于1,那么直接返回false,不满足平衡二叉树。
  3. 如果高度差的绝对值小于等于1,则说明该结点满足平衡二叉树,那么就再去看剩下的结点是否满足要求,即:把该结点的左右结点分别作为参数来递归。

因为只有当每个结点都满足它的子树的高度差绝对值不大于1,才能算是平衡二叉树,所以对每一个结点都得查它们左右子树的高度。

class Solution {
   
    public boolean isBalanced(TreeNode root) {
   
        if(root == null)   //情况1
            return true;
        int x = Math.abs(TreeDepth(root.left)-TreeDepth(root.right));
        if(x>1)    //情况2
            return false;
        //情况3
        return isBalanced(root.left)&&isBalanced(root.right);
    }
    public int TreeDepth(TreeNode root){
   
        if(root==null)
            return 0;
        int l=TreeDepth(root.left);
        int r=TreeDepth(root.right);
        return Math.max(l,r)+1;
    }
}

算法二:
(待完善)

6. 二叉树的最小深度

算法: 递归
题目描述:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
本题的思想与第3题二叉树的最大深度几乎完全相同,但有些区别,区别在于:如果左右子树只有一棵的结点为null,该怎么考虑?

  • 在求二叉树的最大深度中,我们对于null结点直接返回为0,若左右子树只有一个为null的话就直接用Math.max()方法找不为空的子树高度,不用去管null结点了,因为它肯定最小,被淘汰了。
  • 但是这道题说的是“从根节点到最近叶子节点”,就不能直接用Math.min()方法取最小值,因为这样得到的子树最小高度一定是0,但实际上null结点不能算作叶子节点,我需要去看不为空的那一棵树,它才是作为根结点的叶子节点的。也就是说如果根结点只有左子树或者只有右子树,我就不能直接取最小值(0),而应该取不为空的子树高度。因此对于子树返回的高度要考虑四种情况:
  1. 左子树高度为0,右子树高度不为0:返回右子树高度+1
  2. 左子树高度不为0,右子树高度为0:返回左子树高度+1
  3. 左右子树高度均不为0:返回二者中最小值+1
  4. 左右子树高度均为0:返回0+1=1

这里“+1”的意思是加上根结点的高度。情况3和情况4可以合并为一种情况,都可以是“最小值+1”,因为0和0取最小值也是0.

class Solution {
   
    public int minDepth(TreeNode root) {
   
        if(root == null)
            return 0;
        int l = minDepth(root.left);
        int r = minDepth(root.right);
        if(l==0 && r!=0)   //情况1
            return r+1;
        if(l!=0 && r==0)    //情况2
            return l+1;
        else      //情况3和4
            return Math.min(l,r)+1;
    }
}

7. 路径总和

题目描述:给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
说明: 叶子节点是指没有子节点的节点。

算法: 递归。题目要求路径必须为根结点到叶子节点,那么最终的结束点一定归结于叶子节点,换句话说就不能在中途停下来,即使可能从根结点到某个中间结点的值加起来等于目标值,也不能算最终路径,因为路径的结尾必须归结到叶子节点。这就说明了本题的解题思路:递归该方法,每一次拿到一个结点和一个目标值,有三种情况:

  1. 该结点为空,说明到结尾了都没找到符合要求的路径,直接返回false
  2. 该结点的左右两个子结点均为空,说明它是叶子节点,那么判断结点值是否与sum相等,相等则返回true,否则返回false
  3. 若不满足子结点为空,说明它不是叶子节点,那就继续往下走,去看它的左右结点是否有符合要求的路径,但这时目标值要改为sum = sum - root.val;
class Solution {
   
    public boolean hasPathSum(TreeNode root, int sum) {
   
        if(root==null)    //情况1
            return false;
        if(root.left==null && root.right==null){
      //情况2,若左右结点为空则说明该结点为叶子节点
            if(root.val == sum)
                return true;
            else return false;
        }
        //情况3
        sum = sum - root.val;
        return hasPathSum(root.left,sum)||hasPathSum(root.right,sum);
    }
}

8. 二叉树的镜像(★★)

题目描述:请完成一个函数,输入一个二叉树,该函数输出它的镜像。
算法: 递归。每次将root结点的左右结点交换位置,再把左右结点作为root递归。

class Solution {
   
    public TreeNode mirrorTree(TreeNode root) {
   
        if(root == null)
            return root;
        TreeNode tem;
        tem = root.left;   //将左右结点交换位置
        root
  • 2
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞行的小猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值