LeetCode刷题 -- 树(三)

给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。

示例 1:
给定的树 s:

 3
/ \

4 5
/
1 2
给定的树 t:

4
/
1 2
返回 true,因为 t 与 s 的一个子树拥有相同的结构和节点值。

示例 2:
给定的树 s:

 3
/ \

4 5
/
1 2
/
0
给定的树 t:

4
/
1 2
返回 false。

class Solution {
    public boolean isSubtree(TreeNode s, TreeNode t) {
    if(s==null) return false;
    return isSubtreeWithRoot(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t);
    }
    public boolean isSubtreeWithRoot(TreeNode s, TreeNode t){
        if(s==null && t == null) return true;
        if(s== null || t== null) return false;
        if(s.val != t.val)  return false;
        return isSubtreeWithRoot(s.left, t.left) && isSubtreeWithRoot(s.right,t.right);
    }
}

101.对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

1

/
2 2
/ \ /
3 4 4 3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

1

/
2 2
\
3 3

class Solution {
    public boolean isSymmetric(TreeNode root) {
     if(root == null) return true;
     return isSymmetric(root.left, root.right);
    }
    public boolean isSymmetric(TreeNode t1 ,TreeNode t2){
        if(t1 == null && t2 == null)  return true;
        if(t1==null || t2==null) return false;
        if(t1.val != t2.val) return false;
        //此处需要对照图,弄明白递归的目的
        //需要比较左子树的左子树和右子树的右子树是否相等
        return isSymmetric(t1.left, t2.right) && isSymmetric(t2.left, t1.right);
    }
}

404. 左叶子之和

计算给定二叉树的所有左叶子之和。

示例:

3

/
9 20
/
15 7

在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

//先求所有结点的和
public int sumOfLeaves(TreeNode root){
    if(root == null) return 0;
    return sumOfLeaves(root.left) + sumOfLeaves(root.right) + root.val;
}
//在此基础上加上限制条件:
//1.叶子结点;2.左半边
public int sumOfLeaves(TreeNode root){
    if(root == null) return 0;
    if(isleaf(root.left)) return root.left.val + sumOfLeaves(root.right);
    return sumOfLeaves(root.left) + sumOfLeaves(root.right);
}
public boolean isleaf(TreeNode node){
    if(node == null) return false;
    return node.left == null && node.right == null;
}

687. 最长同值路径

给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。

注意:两个节点之间的路径长度由它们之间的边数表示。

示例 1:

输入:

          5
         / \
        4   5
       / \   \
      1   1   5

输出:

2
示例 2:

输入:

          1
         / \
        4   5
       / \   \
      4   4   5

输出:

2

class Solution {
    private int res = 0;
    public int longestUnivaluePath(TreeNode root) {
       calculate(root);
       return res;
    }

    public int calculate(TreeNode root){
        if(root == null) return 0;
        int leftCount = calculate(root.left);  //递归的目的,计算左子树路径,计算右子树路径
        int rightCount = calculate(root.right);

        int left = 0 ;//设置一个默认的值标识初始的路径,一般是0
        int right =0;
        if(root.left != null && root.left.val == root.val) {
            left = leftCount +1; //加入到路径中去
        }
        if(root.right != null && root.right.val == root.val){
            right = rightCount +1;
        }
        res = Math.max(res, left + right);
        return Math.max(left, right);//返回一个最长路径到上层,上层并不管你是怎么计算的,只需要一个最长的路径
    }
}

337.打家劫舍(三)

在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。

示例 1:

输入: [3,2,3,null,3,null,1]

 3
/ \

2 3
\ \
3 1

输出: 7
解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.
示例 2:

输入: [3,4,5,1,3,null,1]

 3
/ \

4 5
/ \ \
1 3 1

输出: 9
解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.

class Solution {
    public int rob(TreeNode root) {
      if(root == null) return 0;
      int val1 = root.val;
      //偷root,root的孙子结点
      if(root.left != null) val1+= rob(root.left.left)+ rob(root.left.right);
      if(root.right != null) val1+= rob(root.right.left)  + rob(root.right.right);
      //不偷root ,偷root的左子树和右子树
      //以root的左右子树为根结点开始
      int val2 = rob(root.left) + rob(root.right);
      return Math.max(val1, val2);
    }
}

671. 二叉树第二小的结点

给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么这个节点的值不大于它的子节点的值。

给出这样的一个二叉树,你需要输出所有节点中的第二小的值。如果第二小的值不存在的话,输出 -1 。

示例 1:

输入:
2
/
2 5
/
5 7

输出: 5
说明: 最小的值是 2 ,第二小的值是 5 。
示例 2:

输入:
2
/
2 2

输出: -1
说明: 最小的值是 2, 但是不存在第二小的值。

class Solution {
    public int findSecondMinimumValue(TreeNode root) {
     if(root == null) return -1;
     if(root.left == null && root.right == null) return -1;
     //根节点一定是最小值,所以第二小的一定在左子树或者右子树中

     int leftVal = root.left.val;
     int rightVal = root.right.val;
     
     //说明左子树下面的值一定是大于左子树的根的,第二小可能在左子树中产生
     if(leftVal == root.val) leftVal = findSecondMinimumValue(root.left);

     if(rightVal == root.val) rightVal = findSecondMinimumValue(root.right);
     
     //说明左右子树都非空
     if(leftVal != -1 && rightVal != -1 ){
         return Math.min(leftVal, rightVal);
     }

     if(leftVal != -1) return leftVal;
     return rightVal;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值