代码随想录-2023/07/15

71 阅读1分钟

二叉树的应用

513.找树左下角的值

  1. 注意: 其实就是找最后一层的第一个出现的元素, 并不是找左子节点
  2. 层序遍历---记录最后一层第一个出现的值即可

代码:

class Solution {
    // 注意最左边的节点不一定是左节点
    public int findBottomLeftValue(TreeNode root) {
        int ans = 0;
        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.offerLast(root);
        while(!deque.isEmpty()){
            int size = deque.size();
            for(int i=0; i<size; i++){
                TreeNode t = deque.pollFirst();
                if(i == 0) ans = t.val;
                if(t.left != null) deque.offerLast(t.left);
                if(t.right != null) deque.offerLast(t.right);
            }
        }

        return ans;

    }
}

112.路径总和

递归一般有返回值(结果返回到上一层递归)---回溯一般没有返回值(用全局变量保存结果)

  1. 存在一种, 则用sum记录路径和, 若找到直接返回true, 未找到则继续递归遍历
  2. 若求所有路径, 则需要回溯法记录所有结果 代码:
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        return dfs(root, targetSum, 0);
    }
    // 递归一般有返回值---回溯一般没有返回值
    public boolean dfs(TreeNode root, int targetSum, int sum) {
        // 遍历到null
        if(root == null) return false;
        // 2.遍历到叶子节点
        if(root.left == null && root.right == null) {
            return sum + root.val == targetSum;
        }
        // 3.递归遍历子节点, 只要存在 true, 就向上返回
        return dfs(root.left, targetSum, sum + root.val) || dfs(root.right, targetSum, sum + root.val); 
    }
}

113.路径总和II

回溯法: 每遍历一个节点就计算当前路径和,然后将节点值加入到集合lis中, 若遍历到叶子节点需要判断sum是否等于targetSum, 若相等则需要保存结果, 同时需要回溯当前叶子节点, 当遍历完当前节点的左右子节点时, 需要回溯当前节点

代码:

class Solution {
    List<List<Integer>> ans = new ArrayList<>();
    LinkedList<Integer> list = new LinkedList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        backtracking(root, targetSum, 0);
        return ans;
    }
    
    public void backtracking(TreeNode root, int targetSum, int sum) {
        if(root == null) return;
        list.add(root.val);
        if(root.left == null && root.right == null) {
            if(sum+root.val == targetSum){
                ans.add(new ArrayList<>(list));
            }   
            list.removeLast();
            return;
        } 
        backtracking(root.left, targetSum, sum+root.val);
        backtracking(root.right, targetSum, sum+root.val);
        list.removeLast();
    }

}

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

递归法:

  1. 从后序数组中取得最后一个数字, 作为当前的根节点
  2. 在中序数组中找到根节点的位置, 所以根节点左边的节点为下一次递归的左子树范围, 根节点右边的节点为下一次递归的右子树的范围
  3. 计算左子树元素个数
  4. 下一次递归的后序数组范围的左边元素个数 = 中序数组的下一次递归的左边元素个数
  5. 下一次递归的后序数组范围的右边元素个数 = 中序数组的下一次递归的右边元素个数

代码:

class Solution {
    HashMap<Integer, Integer> map = new HashMap<>();
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        for(int i=0; i<inorder.length; i++){
            map.put(inorder[i], i);
        }
        return dfs(inorder, 0, inorder.length, postorder, 0, postorder.length);
    }
    // 左闭右开区间
    public TreeNode dfs(int[] inorder, int in_start, int in_end, int[] postorder, int p_start, int p_end){
        if(in_start >= in_end || p_start >= p_end) {
            return null;
        }
        // 构建当前节点
        int index = map.get(postorder[p_end-1]);
        TreeNode root = new TreeNode(inorder[index]) ;
       
        // 记录左边的元素个数---确保元素个数相同
        int size = index - in_start;

        // 构建左子节点
        root.left = dfs(inorder, in_start, index, postorder, p_start, p_start + size);

        // 构建右子节点
        root.right = dfs(inorder, index + 1, in_end, postorder, p_start + size, p_end - 1);

        // 返回当前节点
        return root;

    }

   
}