一、#513.找树左下角的值
关键思路:这个题使用层序遍历(迭代法)更容易一些
解法一:递归法
先求出深度最大的一层,然后找这一层最左边的节点
此题用前序后序中序都可以,因为没有对根节点有操作,只要保证先是左再是右就行
class Solution {
int maxDepth = -1; //记录最大深度
int res = 0; //记录最大深度的值
public int findBottomLeftValue(TreeNode root) {
trv(root, 0);
return res;
}
private void trv(TreeNode node, int depth){
//根节点:判断深度,是最深的就记录值
if(node.left == null && node.right == null){
if(depth > maxDepth){
res = node.val;
maxDepth = depth;
}
}
//单层逻辑:继续往下判断左右子树
if(node.left != null){
depth++;
trv(node.left, depth);
depth--; //回溯,因为下一循环还要传递这个depth,所以要保证传递的是对的
}
if(node.right != null){
depth++;
trv(node.right, depth);
depth--;
}
}
}
解法二:迭代法
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int res = 0;
while(!queue.isEmpty()){
int size = queue.size();
for(int i = 0; i < size; i++){
TreeNode poll = queue.poll();
if(i == 0){
res = poll.val;
}
if(poll.left != null){
queue.offer(poll.left);
}
if(poll.right != null){
queue.offer(poll.right);
}
}
}
return res;
}
offer()是 Queue 接口的一个方法,用于将一个元素插入到队列的尾部。
二、#112. 路径总和
关键思路:逐步递减,最后总和是0,且是叶子节点,就是有
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) return false;
targetSum -= root.val;
if(root.left == null && root.right == null){
return targetSum==0;
}
if(root.left != null){
boolean left = hasPathSum(root.left, targetSum);
if(left){
return true;
}
}
if(root.right != null){
boolean right = hasPathSum(root.right, targetSum);
if(right){
return true;
}
}
return false;
}
}
三、#113. 路径总和ii
关键思路:
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> res = new ArrayList<>();
if(root == null) return res;
List<Integer> path = new LinkedList<>();
pre(root, targetSum, res, path);
return res;
}
private void pre(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> path){
path.add(root.val);
if(root.left == null && root.right == null){
if(targetSum - root.val == 0){
res.add(new ArrayList<>(path));
}
return;
}
if(root.left != null){
pre(root.left,targetSum-root.val,res,path);
path.remove(path.size()-1);
}
if(root.right != null){
pre(root.right,targetSum-root.val,res,path);
path.remove(path.size()-1);
}
}
}
四、#106.从中序与后序遍历序列构造二叉树
关键思路:
根据前或后序找根节点;
然后在中序中切割前半(左子树)和后半(右子树)
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(postorder.length == 0 || inorder.length == 0) return null;
return trv(inorder, 0, inorder.length, postorder, 0, postorder.length);
}
private TreeNode trv(int[] inorder, int inorderStart, int inorderEnd, int[] postorder, int postorderStart, int postorderEnd){
if(postorderStart == postorderEnd) return null;
int rootVal = postorder[postorderEnd - 1];
TreeNode root = new TreeNode(rootVal);
int middle;
for(middle = inorderStart; middle < inorderEnd; middle++){
if(inorder[middle] == rootVal)
break;
}
//切割
int leftInorderStart = inorderStart;
int leftInorderEnd = middle;
int rightInorderStart = middle + 1;
int rightInorderEnd = inorderEnd;
int leftPostorderStart = postorderStart;
int leftPostorderEnd = postorderStart + (middle - inorderStart);
int rightPostorderStart = leftPostorderEnd;
int rightPostorderEnd = postorderEnd-1;
root.left = trv(inorder, leftInorderStart,leftInorderEnd, postorder, leftPostorderStart, leftPostorderEnd);
root.right = trv(inorder, rightInorderStart, rightInorderEnd, postorder, rightPostorderStart, rightPostorderEnd);
return root;
}
}