玩转算法 第四天 二叉树与递归

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],

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

111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],

    public int minDepth(TreeNode root) {
        if(root==null) return 0;

        if(root.left==null&&root.right!=null) return minDepth(root.right)+1;  

        if(root.right==null&&root.left!=null) return minDepth(root.left)+1; 

        return Math.min(minDepth(root.left),minDepth(root.right))+1;
    }

226. 翻转二叉树

翻转一棵二叉树。
在这里插入图片描述

class Solution {
    public TreeNode invertTree(TreeNode root) {

        if(root==null) return root;

        TreeNode temp=invertTree(root.left);
        root.left=invertTree(root.right); 
        root.right=temp;
        return root; 
    }
}

110. 平衡二叉树

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

在这里插入图片描述

   public boolean isBalanced(TreeNode root) {
        if(root==null) return true;
        return Math.abs(height(root.left)-height(root.right))<=1&&isBalanced(root.left)&&isBalanced(root.right) ;
        
    }

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

101. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。
在这里插入图片描述

    public boolean isSymmetric(TreeNode root) {   
        if(root==null) return true;
        return recur(root.left,root.right);
    }
 
    public boolean recur(TreeNode A,TreeNode B){
        if(A==null&&B==null) return true; 
        if(A==null||B==null) return false;
        if(A.val==B.val) 
        return recur(A.left,B.right)&&recur(A.right,B.left);
         return false;     
    } 

100. 相同的树

给定两个二叉树,编写一个函数来检验它们是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
在这里插入图片描述

 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 false;
        return  isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
    }

222. 完全二叉树的节点个数

给出一个完全二叉树,求出该树的节点个数。
说明:
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
在这里插入图片描述

class Solution {
   public int countNodes(TreeNode root) {
        //分治前序遍历
        return root==null ? 0 : countNodes(root.left)+countNodes(root.right)+1;
    }
}

113. 路径总和 II

输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。
在这里插入图片描述

   List<Integer> list=new ArrayList<>();
     List<List<Integer>> res=new ArrayList<>(); 
    public List<List<Integer>> pathSum(TreeNode root, int sum) { 
     if(root==null) return res;
     list.add(root.val);
     sum-=root.val;
     if(sum==0&&root.left==null&&root.right==null){
         res.add(new ArrayList(list)); 
     }
      pathSum(root.left,sum);
      pathSum(root.right,sum);
     list.remove(list.size()-1);   
      return res; 
  }

112. 路径总和

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

 
public boolean hasPathSum(TreeNode root, int sum) {
       //根节点为空,直接返回false
        if (root == null) {
            return false;
        }
        // 到达叶子节点时,递归终止,判断 sum 是否符合条件。
        if (root.left == null && root.right == null) {
            return root.val == sum;
        }
        // 递归地判断root节点的左孩子和右孩子。
        return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);
    }

 

404. 左叶子之和

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

在这里插入图片描述

解法1
    public int sumOfLeftLeaves(TreeNode root) {
      if(root==null) return 0; 
      int sum=0;
      if(root.left!=null&&root.left.right==null&&root.left.left==null) sum+=root.left.val; 
     return sumOfLeftLeaves(root.left)+sumOfLeftLeaves(root.right)+sum; 
    }
解法2
public int sumOfLeftLeaves(TreeNode root) {
      if(root==null) return 0; 
      int sum=0;
      if(root.left!=null&&root.left.right==null&&root.left.left==null)
      return root.left.val+sumOfLeftLeaves(root.right);
      return  sumOfLeftLeaves(root.left)+sumOfLeftLeaves(root.right); 
    }

257. 二叉树的所有路径

给定一个二叉树,返回所有从根节点到叶子节点的路径。说明: 叶子节点是指没有子节点的节点。

在这里插入图片描述

思路1 
  private List<String> res = new ArrayList<>();

    public List<String> binaryTreePaths(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        dfs(root, sb);
        return res;
    }

    public void dfs(TreeNode root, StringBuilder sbr) {
        if (root == null) return;
        StringBuilder sb = new StringBuilder(sbr);
        sb.append(root.val);
        if (root.left == null && root.right == null) {
            res.add(sb.toString());
            return;
        }
        sb.append("->");
        dfs(root.left, sb);
        dfs(root.right, sb);
    }


思路2

   ArrayList<String> res=new ArrayList<>();
    public List<String> binaryTreePaths(TreeNode root) {
        if(root==null) return res;
        dfs(root,"");
        return res;
    }
    
    public void dfs(TreeNode root,String str){
        if(root.left!=null)
            dfs(root.left,str+root.val+"->");
        if(root.right!=null)
            dfs(root.right,str+root.val+"->");      
        if(root.left==null&&root.right==null)
            res.add(str+root.val); 
    } 

129. 求根到叶子节点数字之和

给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字。例如,从根到叶子节点路径 1->2->3 代表数字 123。计算从根到叶子节点生成的所有数字之和。说明: 叶子节点是指没有子节点的节点。
在这里插入图片描述

class Solution {
      int sum=0;
        public int sumNumbers(TreeNode root) {
            dfs(root,0);
            return sum;
        }

         public void dfs(TreeNode root,int temp){
           if(root==null) return;
           if(root.left==null&&root.right==null) {
               sum += temp * 10 + root.val;
               return;
           }
            dfs(root.left,10*temp+root.val);
            dfs(root.right,10*temp+root.val);
       }

}

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

//二叉树
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
      
        if(root==null||root==p||root==q) return root;
        
        TreeNode left=lowestCommonAncestor(root.left,p,q);

        TreeNode right=lowestCommonAncestor(root.right,p,q);

        if(left==null) return right;

        if(right==null) return left;

        return root;
    }
}

//二叉搜索树
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root==null) return root;
         if(p.val<root.val&&q.val<root.val) {
          return  lowestCommonAncestor(  root.left,   p,   q);
         }
        if(p.val>root.val&&q.val>root.val){
          return  lowestCommonAncestor(  root.right,  p,   q);
         }
         return root;

    }
}

98. 验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
在这里插入图片描述

 /**
     *
     *  方法一: 递归
     *
     * @param root
     * @return
     */

    public boolean isValidBST(TreeNode root) {
        return helper(root, null, null);
    }


    public boolean helper(TreeNode node, Integer lower, Integer upper) {
        if (node == null) return true;

        int val = node.val;
        if (lower != null && val <= lower) return false;
        if (upper != null && val >= upper) return false;

        if (! helper(node.right, val, upper)) return false;
        if (! helper(node.left, lower, val)) return false;
        return true;
    }


/**
 *
 * 方法2 中序遍历 时间复杂度O(N) 空间复杂度O(N)
 *
 *
 */



       public boolean isValidBST2(TreeNode root) {
           Stack<TreeNode> stack=new Stack<>();
           Integer a=null;
           while(!stack.isEmpty()||root!=null) {
               if (root != null) {
                   stack.push(root);
                   root = root.left;
               } else {
                   TreeNode temp=stack.pop();
                   if(a!=null&&temp.val<=a) return false;
                   a=temp.val;
                   root=temp.right;
               }
           }
             return true;

       }

230. 二叉搜索树中第K小的元素

给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。说明:你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。
在这里插入图片描述

class Solution {
   ArrayList<Integer> res=new ArrayList<>();
    public int kthSmallest(TreeNode root, int k) {
        recur(root);
        return res.get(k-1);
    }
    
    public void recur(TreeNode root){
        if(root==null) return;
        if(root.left!=null) recur(root.left);
        res.add(root.val);
        if(root.right!=null) recur(root.right);
    } 
}

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

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
在这里插入图片描述

public TreeNode sortedArrayToBST(int[] nums) {
        // 左右等分建立左右子树,中间节点作为子树根节点,递归该过程
        return nums == null ? null : recur(nums, 0, nums.length - 1);
    }

          public TreeNode recur(int nums[],int l,int r){
              if(l>r) return null;
              int mid=(l+r)>>1;
              TreeNode root=new TreeNode(nums[mid]);
              root.left=recur(nums,0,mid-1);
              root.right=recur(nums,mid+1,r);
              return root;
     }

450. 删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。在这里插入图片描述

437. 路径总和 III

给定一个二叉树,它的每个结点都存放着一个整数值。找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
在这里插入图片描述

剑指 Offer 26. 树的子结构

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)B是A的子结构, 即 A中有出现和B相同的结构和节点值。
例如:给定的树 A:

class Solution {
    public boolean isSubtree(TreeNode s, TreeNode t) {
        if(A==null&&B==null) return true;
        // if(A==null||B==null) return false;
        recur(s,t);
   
    }

    public boolean recur(TreeNode A,TreeNode B){}{
          if(B==null) return true;
          if(A==null) return false;
          if(A.val==B.val){
           return recur(A.left,B.left)&&recur(A.right,B.right);
          }  
    }   
}

572. 另一个树的子树

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

class Solution {
    public boolean isSubtree(TreeNode s, TreeNode t) {
        if(s==null&&t==null) return true; 
        if(s==null||t==null) return false;
        //两棵树是否相等,s左子树和t相等,s右子树和t相等
       return recur(s,t)||isSubtree(s.left,t)||isSubtree(s.right,t);
    }


    //判断两棵树是否相等,根节点值相等,左子树和右子树一样
    public boolean recur(TreeNode A,TreeNode B){
          if(B==null&&A==null) return true;
          if(A==null||B==null) return false; 
          return  A.val==B.val&&recur(A.left,B.left)&&recur(A.right,B.right); 
    }    
}

617. 合并二叉树

给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

示例 1:

   public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
         if(t1==null) return t2;
         if(t2==null) return t1;
           // 先合并根节点
         t1.val += t2.val;
           // 再递归合并左右子树
         t1.left=mergeTrees(t1.left,t2.left);
         t1.right=mergeTrees(t1.right,t2.right);
         return t1; 

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值