代码随想录算法训练营第十六天-513找树左下角的值、112路径总和、113路径总和ii、106从中序与后序遍历序列构造二叉树、105从前序与中序遍历序列构造二叉树
初步题解
513 找树左下角的值
题目链接:(https://leetcode.cn/problems/find-bottom-left-tree-value)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
public int findBottomLeftValue(TreeNode root) { List<List<Integer>> list = new ArrayList<>(); findBottomDFS(root, 0, list); List<Integer> theLastLayer = list.get(list.size() - 1); return theLastLayer.stream().filter(Objects::nonNull).collect(Collectors.toList()).get(0); } private void findBottomDFS(TreeNode root, int i, List<List<Integer>> list) { if (root == null) { return; } i++; if (list.size() < i) { ArrayList<Integer> innerList = new ArrayList<>(); list.add(innerList); } list.get(i - 1).add(root.val); findBottomDFS(root.left, i, list); findBottomDFS(root.right, i, list); }
|
112 路径总和、113 路径总和 ii
题目链接:(https://leetcode.cn/problems/path-sum/description/)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
public boolean hasPathSum(TreeNode root, int targetSum) { if (root == null) { return false; } List<Integer> list = new ArrayList<Integer>(); return hasPathSumBFS(root, list, targetSum); } private boolean hasPathSumBFS(TreeNode root, List<Integer> list, int targetSum) { list.add(root.val); if (root.left == null && root.right == null) { long sum = list.stream().collect(Collectors.summarizingInt(value -> value)).getSum(); return sum == targetSum; } boolean left = false; boolean right = false; if (root.left != null) { left = hasPathSumBFS(root.left, list, targetSum); list.remove(list.size() - 1); } if (root.right != null) { right = hasPathSumBFS(root.right, list, targetSum); list.remove(list.size() - 1); } return left || right; }
|
题目链接:(https://leetcode.cn/problems/path-sum-ii/)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public static List<List<Integer>> pathSum(TreeNode root, int targetSum) { List<Integer> list = new ArrayList<>(); List<List<Integer>> result = new ArrayList<>(); pathSumBFS(root, targetSum, result, list); return result; } private static void pathSumBFS(TreeNode root, int targetSum, List<List<Integer>> result, List<Integer> list) { if (root == null) { return; } targetSum -= root.val; list.add(root.val); if (root.left == null && root.right == null) { if (targetSum == 0) { List<Integer> arrayList = new ArrayList<>(list); result.add(arrayList); } } if (root.left != null) { pathSumBFS(root.left, targetSum, result, list); list.remove(list.size() - 1); } if (root.right != null) { pathSumBFS(root.right, targetSum, result, list); list.remove(list.size() - 1); } }
|
106 从中序与后序遍历序列构造二叉树、105 从前序与中序遍历序列构造二叉树
题目链接:(https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/)
题目链接:(https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
更快的解法是把 inorder 放到 map 内,这样查找不用遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public static TreeNode buildTree(int[] preorder, int[] inorder) { if (preorder.length == 0) { return null; } TreeNode root = new TreeNode(preorder[0]); if (preorder.length == 1) { return root; } int indexIn = -1; for (int i = 0; i < inorder.length; i++) { if (inorder[i] == preorder[0]) { indexIn = i; break; } } int[] leftTreeInorder = Arrays.copyOfRange(inorder, 0, indexIn); int[] rightTreeInorder = Arrays.copyOfRange(inorder, indexIn + 1, inorder.length); root.left = buildTree(Arrays.copyOfRange(preorder, 1, leftTreeInorder.length + 1), leftTreeInorder); root.right = buildTree(Arrays.copyOfRange(preorder, inorder.length - rightTreeInorder.length, inorder.length), rightTreeInorder); return root; }
|
看解析
513 找树左下角的值
题目链接/文章讲解/视频讲解:(https://programmercarl.com/0513.找树左下角的值.html)
那么如何找最左边的呢?可以使用前序遍历(当然中序,后序都可以,因为本题没有 中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| int value; int maxDeep = Integer.MIN_VALUE; public int findBottomLeftValueBFS(TreeNode root) { value = root.val; findLeftValue(root,0); return value; } private void findLeftValue(TreeNode root, int deep) { if (root == null) { return; } if (root.left == null && root.right == null) { if (deep > maxDeep) { value = root.val; maxDeep = deep; } } if (root.left != null) { findLeftValue(root.left, deep + 1); } if (root.right != null) { findLeftValue(root.right, deep + 1); } }
|
112 路径总和、113 路径总和 ii
题目链接/文章讲解/视频讲解:(https://programmercarl.com/0112.路径总和.html)
绕晕了,如果把 targetSum -= root.val;
这句话写在函数最前面,就不用回溯。可以看三行简化的那个注释。我理解的是 Java 里 int 不能传递值,递归内层对 targetSum 的值进行改变,外层不会变化,所以就不用回溯了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
public static boolean hasPathSum(TreeNode root, int targetSum) { if (root == null) { return false; } targetSum -= root.val; return hasPathSumBFS(root, targetSum); } private static boolean hasPathSumBFS(TreeNode root, int targetSum) { if (root.left == null && root.right == null) { return targetSum == 0; } if (root.left != null) { targetSum -= root.left.val; if (hasPathSumBFS(root.left, targetSum)) { return true; } targetSum += root.left.val; }
if (root.right != null) { targetSum -= root.right.val; if (hasPathSumBFS(root.right, targetSum)) { return true; } targetSum += root.right.val; } return false; }
public static boolean hasPathSum(TreeNode root, int targetSum) { if (root == null) { return false; } if (root.left == null && root.right == null) { return targetSum == 0; } return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val); }
|
106 从中序与后序遍历序列构造二叉树、105 从前序与中序遍历序列构造二叉树
题目链接/文章讲解/视频讲解:(https://programmercarl.com/0106.从中序与后序遍历序列构造二叉树.html)
更快的解法是把 inorder 放到 map 内,这样查找不用遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
public static TreeNode buildTree(int[] inorder, int[] postorder) { if (inorder.length != postorder.length) { return null; } if (postorder.length == 0) { return null; } TreeNode root = new TreeNode(postorder[postorder.length - 1]); if (postorder.length == 1) { return root; } int indexIn = -1; for (int i = 0; i < inorder.length; i++) { if (inorder[i] == postorder[postorder.length - 1]) { indexIn = i; break; } } int[] leftTreeInorder = Arrays.copyOfRange(inorder, 0, indexIn); int[] rightTreeInorder = Arrays.copyOfRange(inorder, indexIn + 1, inorder.length); root.left = buildTree(leftTreeInorder, Arrays.copyOfRange(postorder, 0, leftTreeInorder.length)); root.right = buildTree(rightTreeInorder, Arrays.copyOfRange(postorder, leftTreeInorder.length, postorder.length - 1)); return root; }
|