513. 找树左下角的值
- 层序遍历法(取最后一层的第一个值)
class Solution {
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> que = new LinkedList<TreeNode>();
if(root == null) return 0;
int res = 0;
que.offer(root);
while(!que.isEmpty()){
int size = que.size();
for(int i = 0; i< size; i++){
TreeNode node = que.poll();
if(i == 0) res = node.val;
if(node.left != null) que.offer(node.left);
if(node.right != null) que.offer(node.right);
}
}
return res;
}
}
- 递归 + 回溯
class Solution {
int maxDepth = Integer.MIN_VALUE;
int res = 0;
public int findBottomLeftValue(TreeNode root) {
traversal(root,0);
return res;
}
public void traversal(TreeNode root, int depth){
if(root.left == null && root.right == null){
if(depth > maxDepth){
maxDepth = depth;
res = root.val;
}
return;
}
if(root.left != null){
depth++;
traversal(root.left, depth);
depth--; // 回溯
}
if(root.right != null){
depth++;
traversal(root.right, depth);
depth--; // 回溯
}
}
}
路径总和
这里的递归需要注意的地方是,是从除了根节点以外的节点开始遍历,所以在传参时需要减去根节点的值。
-
- 路径总和
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
// 用节点和与目标值做减法如果为0则有目标路径
if (root == null) return false;
return traversal(root,targetSum - root.val);
}
public boolean traversal(TreeNode root, int target){
if(root.left == null && root.right == null && target == 0)
return true;
if(root.left == null && root.right == null && target != 0)
return false;
// 左
if(root.left != null){
target -= root.left.val;
if(traversal(root.left,target)) return true;
target += root.left.val; // 回溯
}
// 右
if(root.right != null){
target -= root.right.val;
if(traversal(root.right,target)) return true;
target += root.right.val; // 回溯
}
return false;
}
}
- 路径总和ii
以下为小白写法,这里也是把根节点和其他节点分开处理
class Solution {
public List<Integer> path = new LinkedList<>(); // 存放暂时路径
public List<List<Integer>> res = new ArrayList<>(); // 存放结果集
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if(root == null) return res;
path.add(root.val); // 加入根节点
traversal(root,targetSum - root.val);
return res;
}
public void traversal(TreeNode root, int target){
if(root.left == null && root.right == null && target == 0){
res.add(new ArrayList<>(path));
return;
}
if(root.left != null){
path.add(root.left.val);
target -= root.left.val;
traversal(root.left,target);
target += root.left.val;
path.remove(path.size() - 1);
}
if(root.right != null){
path.add(root.right.val);
target -= root.right.val;
traversal(root.right,target);
target += root.right.val;
path.remove(path.size() - 1);
}
}
}
从中序与后序遍历序列构造二叉树
跟着卡哥思路写的第一版,性能不太行,空间时间浪费太多。
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(postorder.length == 0 || inorder.length == 0) return null;
return traversal(inorder,postorder);
}
public TreeNode traversal(int[] inorder, int[] postorder){
if(postorder.length == 0) return null;
int rootValue = postorder[postorder.length - 1];
TreeNode root = new TreeNode(rootValue);
if(postorder.length == 1) return root;
int i = 0;
for(; i<inorder.length; i++){
if(inorder[i] == rootValue) break;
}
// 切割数组左闭右开原则
int[] inLeft = Arrays.copyOfRange(inorder,0,i);
int[] inRight = Arrays.copyOfRange(inorder,i+1,inorder.length);
int[] postLeft = Arrays.copyOfRange(postorder,0,inLeft.length); // 这里需要包含到左侧边界的数字
int[] postRight = Arrays.copyOfRange(postorder,inLeft.length,postorder.length-1); // 这里需要去除最后的根节点
root.left = traversal(inLeft,postLeft);
root.right = traversal(inRight,postRight);
return root;
}
}
- 这里利用哈希表记录中序遍历的数组,这样做非常方便元素的位置查找。
- 把递归传递的参数从新的数组变成数组下标,节约空间。
class Solution {
Map<Integer, Integer> map = new HashMap<>(); // to record the location of each node
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder.length == 0 || postorder.length == 0) return null;
for(int i=0;i<inorder.length;i++){
map.put(inorder[i],i);
}
// 保持左闭右开原则
return findNode(inorder, 0,inorder.length, postorder, 0,postorder.length);
}
public TreeNode findNode(int[] inorder, int inS, int inE, int[] postorder, int postS, int postE){
if(inE <= inS || postE <= postS) return null;
int index = map.get(postorder[postE - 1]); // 找到根节点的位置
TreeNode root = new TreeNode(inorder[index]);
int leftLen = index - inS; // 记录左子树长度
root.left = findNode(inorder, inS, index, postorder, postS, postS + leftLen);
root.right = findNode(inorder, index + 1, inE, postorder, postS + leftLen, postE - 1); // 这里记住要删掉最后的根节点
return root;
}
}