0
点赞
收藏
分享

微信扫一扫

[力扣]二叉树3

ivy吖 2022-05-02 阅读 84

代码随想录[原文指路]

1.左叶子之和[404]

  • 递归
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        //直接通过当前节点是无法判断是否是叶子节点的
        //如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子
        if(root==null) return 0;
        int sum=0;
        if(root.left!=null&&root.left.left==null&&root.left.right==null) {
            sum += root.left.val;
        }
        
        int leftsum = sumOfLeftLeaves(root.left);
        int rightsum = sumOfLeftLeaves(root.right);
        return leftsum+rightsum+sum;
    }
}
  • 栈迭代
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        //直接通过当前节点是无法判断是否是叶子节点的
        //如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子
        if(root==null) return 0;
        int sum=0;
        Stack<TreeNode> stack = new Stack();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            if(node.left!=null && node.left.left==null && node.left.right==null){
                sum += node.left.val;
            }
            if(node.left!=null) stack.push(node.left);
            if(node.right!=null) stack.push(node.right);
        }
        return sum;
    }
}
  • 队列迭代(层序)
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        //直接通过当前节点是无法判断是否是叶子节点的
        //如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子
        if(root==null) return 0;
        int sum=0;
        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            while(size-->0){
                TreeNode node = queue.poll();
                if(node.left!=null){
                    if(node.left.left==null&&node.left.right==null){
                        sum += node.left.val;
                    }else{
                        queue.offer(node.left);
                    }
                }
                if(node.right!=null) queue.offer(node.right);
            }
        }
        return sum;
    }
}

2.找树左下角的值[513]

  • 递归
class Solution {
    //最大深度
    private int maxheight = -1;
    //最左节点的值
    private int value = 0;

    public int findBottomLeftValue(TreeNode root) {
        if(root==null) return 0;
        //本题要求求最深的叶子节点,所以不采取从下向上递归(返回值),而采取从上往下递归(传参)
        findLeftValue(root,0);
        return value;
    }

    private void findLeftValue(TreeNode root,int deep){
        //deep当前深度
        if(root.left==null && root.right==null) {
            if(deep>maxheight){
                value=root.val;
                maxheight=deep;
            }
        }
        if(root.left!=null) findLeftValue(root.left,deep+1);
        if(root.right!=null) findLeftValue(root.right,deep+1);
    }
}
  • 队列迭代(层序)
class Solution {
    public int findBottomLeftValue(TreeNode root) {
        if(root==null) return 0;

        int leftOrder = 0;
        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            leftOrder = queue.peek().val;
            while(size-->0){
                TreeNode node = queue.poll();
                if(node.left!=null) queue.offer(node.left);
                if(node.right!=null) queue.offer(node.right);
            }
        }
        return leftOrder;
    }
}

3.路径总和[112]

  • 递归使用
1.如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值
2.如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值
3.如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回
  • 递归
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root==null) return false;
        //使用累加较麻烦,此处使用累减,每次让targetSum-root.val,若到叶子节点且targetSum=0则找到
        //此题只需要找到一条满足条件的路径就返回,所以此处返回值为Boolean型标记有没有找到满足条件的路径
        targetSum -= root.val;
        if(targetSum==0&&root.left==null&&root.right==null) return true;

        boolean bool1 = hasPathSum(root.left,targetSum);
        boolean bool2 = hasPathSum(root.right,targetSum);

        return bool1||bool2;
    }
}
  • 栈迭代
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root==null) return false;
        //栈里一个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和
        Stack<TreeNode> stack1 = new Stack();
        Stack<Integer> stack2 = new Stack();
        stack1.push(root);
        stack2.push(root.val);
        while(!stack1.isEmpty()){
            int size = stack1.size();
            while(size-->0){
                TreeNode node = stack1.pop();
                int sum=stack2.pop();
                //如果该节点是叶子节点,同时该节点的路径数值等于sum,那么就返回true
                if(node.left==null && node.right==null && sum==targetSum)return true;
                //左节点,压进去一个节点的时候,将该节点的路径数值也记录下来
                if(node.left!=null){
                    stack1.push(node.left);
                    stack2.push(sum+node.left.val);
                }
                //右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
                if(node.right!=null){
                    stack1.push(node.right);
                    stack2.push(sum+node.right.val);
                }
            }
        }
        return false;
    }
}

4.路径总和 II[113]

  • 递归
class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> ress = new ArrayList();
        if(root==null) return ress;
        List<Integer> res = new ArrayList();
        getpathSum(root,targetSum,res,ress);
        return ress;
    }

    public void getpathSum(TreeNode root, int targetSum,List<Integer> res,List<List<Integer>> ress) {
        //使用累加较麻烦,此处使用累减,每次让targetSum-root.val,若到叶子节点且targetSum=0则找到
        //此题需要找到所有满足条件的路径就返回,此处不用返回值  
        res.add(root.val);
        targetSum -= root.val;
        if(root.left==null && root.right==null){
        	//注意此处res的改变直接影响ress,所以此处new
            if(targetSum==0) ress.add(new ArrayList<>(res));
            return ;
        }
        if(root.left!=null){
            getpathSum(root.left,targetSum,res,ress);
            res.remove(res.size()-1);//回溯
        }
        if(root.right!=null){
            getpathSum(root.right,targetSum,res,ress);
            res.remove(res.size()-1);//回溯
        }
    }
}

5.从中序与后序遍历序列构造二叉树[106]

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return treeBuild(inorder,0,inorder.length,postorder,0,postorder.length);
    }

    public TreeNode treeBuild(int[] inorder,int inleft,int inright,int[] postorder,int postleft,int postright){
        //元素为空
        if(inright-inleft<1) return null;
        //只有一个元素
        if(inright-inleft==1) return new TreeNode(inorder[inleft]);
        //保存后序数组最后一个点为切割点,同时构建根节点
        int rootVal = postorder[postright-1];
        TreeNode root = new TreeNode(rootVal);
        //在中序数组中找到该点位置切割
        int rootIndex = 0;
        for(int i=inleft;i<inright;i++){
            if(inorder[i]==rootVal){
                rootIndex=i;
                break;
            }
        }
        //递归构建子树--中序数组以rootIndex切割--后序数组同样以rootIndex切割,注意不包含最后一个节点,但包含toorIndex
        root.left = treeBuild(inorder,inleft,rootIndex,postorder,postleft,postleft+(rootIndex-inleft));
        root.right = treeBuild(inorder,rootIndex+1,inright,postorder,postleft+(rootIndex-inleft),postright-1);
        return root;
    }
}

6.从前序与中序遍历序列构造二叉树[105]

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return treeBuild(inorder,0,inorder.length,preorder,0,preorder.length);    
    }

    public TreeNode treeBuild(int[] inorder,int inleft,int inright,int[] preorder,int preleft,int preright){
        //元素为空
        if(inright-inleft<1) return null;
        //只有一个元素
        if(inright-inleft==1) return new TreeNode(inorder[inleft]);
        //保存前序数组第一个点为切割点,同时构建根节点
        int rootVal = preorder[preleft];
        TreeNode root = new TreeNode(rootVal);
        //在中序数组中找到该点位置切割
        int rootIndex = 0;
        for(int i=inleft;i<inright;i++){
            if(inorder[i]==rootVal){
                rootIndex=i;
                break;
            }
        }
        //递归构建子树--中序数组以rootIndex切割--后序数组同样以rootIndex切割,注意不包含最后一个节点,但包含toorIndex
        root.left = treeBuild(inorder,inleft,rootIndex,preorder,preleft+1,preleft+(rootIndex-inleft));
        root.right = treeBuild(inorder,rootIndex+1,inright,preorder,preleft+(rootIndex-inleft)+1,preright);
        return root;
    }
}

7.最大二叉树[654]

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return buildMaxTree(nums,0,nums.length);
    }

    public static TreeNode buildMaxTree(int[] nums,int leftIndex,int rightIndex){//包左不包右
        //返回条件
        if(rightIndex-leftIndex<1) return null;
        if(rightIndex-leftIndex==1) return new TreeNode(nums[leftIndex]);

        //寻找最大值索引
        int maxIndex = -1;
        int maxVal = 0;
        for(int i=leftIndex;i<rightIndex;i++){
            if(nums[i]>maxVal){
                maxIndex=i;
                maxVal=nums[i];
            }
        }
        //构建最大值为根节点
        TreeNode root = new TreeNode(maxVal);
        //递归构建左右子树
        root.left=buildMaxTree(nums,leftIndex,maxIndex);
        root.right=buildMaxTree(nums,maxIndex+1,rightIndex);
        return root;
    }
}

8.合并二叉树[617]

  • 构建新节点
class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        //返回条件
        if(root1==null) return root2;
        if(root2==null) return root1;

        TreeNode root = new TreeNode(root1.val+root2.val);
        root.left = mergeTrees(root1.left,root2.left);
        root.right = mergeTrees(root1.right,root2.right);
        return root;
    }
}
  • 不建构新节点
class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        //返回条件
        if(root1==null) return root2;
        if(root2==null) return root1;

        root1.val = root1.val+root2.val;
        root1.left = mergeTrees(root1.left,root2.left);
        root1.right = mergeTrees(root1.right,root2.right);
        return root1;
    }
}
举报

相关推荐

0 条评论