2022.03.17 力扣112,113,105,106,654

学习二叉树

follow:代码随想录


112. 路经之和

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

解答:
递归法:
返回值和参数值:返回值是boolean,参数值是根节点+目标值
本题属于搜索二叉树其中一条符合条件的路径,所以递归函数需要返回值
终止条件:节点为空的时候(或者是遍历到了叶节点+没有达到目标值);或者遍历到了叶节点+达到了目标值
单次逻辑:以左右节点为根节点,再次递归

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        //采用前序遍历 + 回溯
        if(root == null) return false;
        if(root.left == null && root.right == null && root.val == targetSum) return true;
        //节点上的数不一定是正数
        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
    }
}

迭代法:

public boolean hasPathSum(TreeNode root, int targetSum) {
        Deque<TreeNode> stack = new LinkedList<>();
        //前序遍历
        int sum = 0;
        if(root == null) return false;
        stack.addFirst(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.peekFirst();
            if(node != null){
                sum += node.val;
                if(node.left == null && node.right == null && sum == targetSum){
                    return true;
                }
                //利用null来标志该节点是否被遍历
                stack.addFirst(null);
                if(node.right != null) stack.addFirst(node.right);
                if(node.left != null) stack.addFirst(node.left);
            }else{
                stack.removeFirst();
                node = stack.removeFirst();
                sum -= node.val;
            }
        }
        return false;
    }
113. 路经总和2⃣️

题目描述:
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
解答:
递归法:这里输入遍历整棵树,递归函数不需要返回值

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<Integer> path = new ArrayList<>();
        countPath(root, targetSum, path);
        return res;
    }

    public void countPath(TreeNode root, int targetSum, List<Integer> path){
        if(root == null) return;
        if(root.left == null && root.right == null && root.val == targetSum){
            path.add(root.val);
            //注意:这里要新建一个arraylist,因为这里是地址传递,后续的path的回溯会改变res中的值
            res.add(new ArrayList<>(path));
            path.remove(path.size() - 1);
            return;
        }
        path.add(root.val);
        if(root.left != null){
            countPath(root.left, targetSum - root.val, path);
        }
        if(root.right != null){
            countPath(root.right, targetSum - root.val, path);

        }
        //回溯
        path.remove(path.size() - 1);
    }
}

迭代法:

public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        Deque<TreeNode> stack = new LinkedList<>();
        if(root != null) stack.addFirst(root);
        int sum = 0;
        while(!stack.isEmpty()){
            TreeNode node = stack.peekFirst();
            if(node != null){
                sum += node.val;
                path.add(node.val);
                if(sum == targetSum && node.left == null && node.right == null){
                    res.add(new ArrayList<>(path));
                }
                stack.addFirst(null);
                if(node.left != null) stack.addFirst(node.left);
                if(node.right != null) stack.addFirst(node.right);
            }else{
                //回溯
                stack.removeFirst();
                node = stack.removeFirst();
                path.remove(path.size() - 1);
                sum -= node.val;
            }
        }
        return res;
    }
105 从前序与中序遍历序列构造二叉树

教程:教程链接

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

    public TreeNode buildSubTree(int[] preorder, int preleft, int preright, int[] inorder, int inleft, int inright){
        if(inright - inleft == 1) return new TreeNode(inorder[inleft]);
        if(inright - inleft < 1) return null; 
        TreeNode root = new TreeNode(preorder[preleft]);
        //找切割点
        int delimiterindex = 0;
        for(delimiterindex = inleft; delimiterindex < inright; delimiterindex++){
            if(inorder[delimiterindex] == preorder[preleft]) break;
        }
        root.left  = buildSubTree(preorder, preleft + 1, preleft + delimiterindex - inleft, inorder, inleft, delimiterindex);
        root.right = buildSubTree(preorder, preleft + delimiterindex - inleft + 1, preright, inorder, delimiterindex + 1, inright);
        return root;
    }
}
106 从中序与后序遍历序列构造二叉树

题目描述:

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

    public TreeNode buildSubTree(int[] inorder, int inleft, int inright, int[] postorder, int postleft, int postright){
        if(inright - inleft == 1) return new TreeNode(inorder[inleft]);
        if(inright - inleft < 1) return null;
        TreeNode root = new TreeNode();
        //找到切割点
        root.val = postorder[postright - 1];
        int delimiterindex = 0;
        for(delimiterindex = inleft; delimiterindex < inorder.length; delimiterindex++){
            if(inorder[delimiterindex] == root.val){
                break;
            }
        }
        //划分子节点 左闭右开   
        root.left = buildSubTree(inorder, inleft, delimiterindex, postorder, postleft, postleft + delimiterindex - inleft);
        root.right = buildSubTree(inorder, delimiterindex + 1, inright, postorder, postleft + delimiterindex - inleft, postright - 1);
        return root;
    }
}
654 最大二叉树

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。

 public TreeNode constructMaximumBinaryTree(int[] nums) {
        return maximumBinaryTree(nums, 0, nums.length);
    }
    //采用递归的方法,传入的参数是相当于切割后的数组
    public TreeNode maximumBinaryTree(int[] nums, int left, int right){
        //该种情况是一侧只有一个元素,则不用再次遍历
        if(right - left == 1) return new TreeNode(nums[left]);
        //某一侧没有元素
        if(right - left < 1) return null;
        int max_index = sort(nums, left, right);
        TreeNode root = new TreeNode(nums[max_index]);
        //前序遍历 分别找到左右节点
        root.left = maximumBinaryTree(nums, left, max_index);
        root.right = maximumBinaryTree(nums, max_index + 1, right);
        return root;
    }

    public int sort(int[] nums, int left, int right){
        int temp = 0;
        int record = -1;
        for(int i = left; i < right; i++){
            if(nums[i] > record)
            {
                temp = i;
                record = nums[i];
            } 
        }
        return temp;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值