第六章 二叉树 part05
大纲
● 513.找树左下角的值
● 112. 路径总和 113.路径总和ii
● 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树
leetcode 513
找树左下角的值
思路
- 递归法 注意回溯思想的运用
- 传递的参数depth+1 隐藏回溯
- 迭代法
- 直接使用队列层次遍历寻找深度最深的第一个叶子结点即可
代码
class Solution {
int res = 0;
int maxDepth = -1;
public int findBottomLeftValue(TreeNode root) {
traverse(root, 0);
return res;
}
public void traverse(TreeNode node, int depth) {
if (node == null) return;
if (node.left == null && node.right == null)
if (depth > maxDepth) {
res = node.val;
maxDepth = depth;
}
if (node.left != null) traverse(node.left, depth + 1);
if (node.right != null) traverse(node.right, depth + 1);
}
}
class Solution {
public int findBottomLeftValue(TreeNode root) {
int res = root.val;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if (i == 0) res = node.val;
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
return res;
}
}
leetcode 112
路径总和
思路
- 递归注意使用目标值递减的方法回溯递归
- 迭代法
- 注意可使用两栈分别保存结点和当前值
- 也可以使用一栈保存两值 注意值读取顺序
- 使用一栈会节省30%的内存空间
代码
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;
if (root.left == null && root.right == null && targetSum == root.val) return true;
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}
}
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;
Stack<TreeNode> s1 = new Stack<>();
Stack<Integer> s2 = new Stack<>();
s1.push(root);
s2.push(root.val);
while (!s1.isEmpty()) {
int size = s1.size();
for (int i = 0; i < size; i++) {
TreeNode node = s1.pop();
int sum = s2.pop();
if (node.left == null && node.right == null && sum == targetSum) return true;
if (node.right != null) {
s1.push(node.right);
s2.push(sum + node.right.val);
}
if (node.left != null) {
s1.push(node.left);
s2.push(sum + node.left.val);
}
}
}
return false;
}
}
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;
Stack<Object> stack = new Stack<>();
stack.push(root);
stack.push(root.val);
while (!stack.isEmpty()) {
int size = stack.size();
for (int i = 0; i < size; i += 2) {
int sum = (Integer) stack.pop();
TreeNode node = (TreeNode) stack.pop();
if (node.left == null && node.right == null && sum == targetSum) return true;
if (node.right != null) {
stack.push(node.right);
stack.push(sum + node.right.val);
}
if (node.left != null) {
stack.push(node.left);
stack.push(sum + node.left.val);
}
}
}
return false;
}
}
leetcode 113
(路径总和ii)[https://leetcode.cn/problems/path-sum-ii]
思路
- 递归法注意回溯减法逼近给定值
- 迭代法使用栈保存结点和路径
代码
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
traverse(root, targetSum);
return res;
}
public void traverse(TreeNode node, int targetSum) {
if (node == null) return;
path.add(node.val);
if (node.left == null && node.right == null && node.val == targetSum) {
res.add(new ArrayList<Integer>(path));
return;
}
if (node.left != null){
traverse(node.left, targetSum - node.val);
path.remove(path.size() - 1);
}
if (node.right != null) {
traverse(node.right, targetSum - node.val);
path.remove(path.size() - 1);
}
}
}
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Stack<Object> stack = new Stack<>();
stack.push(root);
List<Integer> path = new ArrayList<>();
path.add(root.val);
stack.push(path);
while (!stack.isEmpty()) {
path = (List<Integer>) stack.pop();
TreeNode node = (TreeNode) stack.pop();
if (node.left == null && node.right == null && sum(path) == targetSum)
res.add(new ArrayList<Integer>(path));
if (node.right != null){
stack.push(node.right);
stack.push(concat(path, node.right.val));
}
if (node.left != null) {
stack.push(node.left);
stack.push(concat(path, node.left.val));
}
}
return res;
}
public int sum(List<Integer> list) {
int sum = 0;
for (Integer i : list) sum += i;
return sum;
}
public List<Integer> concat(List<Integer> path, int i) {
List<Integer> res = new ArrayList<>(path);
res.add(i);
return res;
}
}
leetcode 106
(从中序与后序遍历序列构造二叉树)[https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal]
思路
- 根据中序遍历和后序遍历特点来递归构造二叉树
- 中序遍历 左根右, 后序遍历 左右根
- 从根的位置确定左右子树从而实现递归构造
代码
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder.length == 0 || postorder.length == 0) return null;
TreeNode root = new TreeNode(postorder[postorder.length - 1]);
for (int i = 0; i < inorder.length; i++) {
if (postorder[postorder.length - 1] == inorder[i]) {
int[] inorderLeft = Arrays.copyOfRange(inorder, 0, i);
int[] inorderRight = Arrays.copyOfRange(inorder, i + 1, inorder.length);
int[] postorderLeft = Arrays.copyOfRange(postorder, 0, i);
int[] postorderRight = Arrays.copyOfRange(postorder, i, postorder.length - 1);
root.left = buildTree(inorderLeft, postorderLeft);
root.right = buildTree(inorderRight, postorderRight);
break;
}
}
return root;
}
}
leetcode 105
(从前序与中序遍历序列构造二叉树)[]
思路
- 同理后序 前序为根左右
代码
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder.length == 0 || inorder.length == 0) return null;
TreeNode root = new TreeNode(preorder[0]);
for (int i = 0; i < preorder.length; i++) {
if (preorder[0] == inorder[i]) {
int[] preorderLeft = Arrays.copyOfRange(preorder, 1, i + 1);
int[] preorderRight = Arrays.copyOfRange(preorder, i + 1, preorder.length);
int[] inorderLeft = Arrays.copyOfRange(inorder, 0, i);
int[] inorderRight = Arrays.copyOfRange(inorder, i + 1, inorder.length);
root.left = buildTree(preorderLeft, inorderLeft);
root.right = buildTree(preorderRight, inorderRight);
break;
}
}
return root;
}
}