二叉树的应用
513.找树左下角的值
- 注意: 其实就是找最后一层的第一个出现的元素, 并不是找左子节点
- 层序遍历---记录最后一层第一个出现的值即可
代码:
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.路径总和
递归一般有返回值(结果返回到上一层递归)---回溯一般没有返回值(用全局变量保存结果)
- 存在一种, 则用sum记录路径和, 若找到直接返回true, 未找到则继续递归遍历
- 若求所有路径, 则需要回溯法记录所有结果 代码:
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. 从中序与后序遍历序列构造二叉树
递归法:
- 从后序数组中取得最后一个数字, 作为当前的根节点
- 在中序数组中找到根节点的位置, 所以根节点左边的节点为下一次递归的左子树范围, 根节点右边的节点为下一次递归的右子树的范围
- 计算左子树元素个数
- 下一次递归的后序数组范围的左边元素个数 = 中序数组的下一次递归的左边元素个数
- 下一次递归的后序数组范围的右边元素个数 = 中序数组的下一次递归的右边元素个数
代码:
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;
}
}