题目链接: 找树左下角的值
自己的思路:层序遍历(超级简单)!!
正确思路:层序遍历、递归
层序遍历代码:
class Solution {
public int findBottomLeftValue(TreeNode root) {
LinkedList<TreeNode> queue = new LinkedList<>();
//存最后的结果
int res = 0;
if (root!=null) queue.add(root);
while(!queue.isEmpty()){
int size = queue.size();
//如果为每一层的第一个,则给res赋值
res = queue.peek().val;
while(size--!=0){
TreeNode node = queue.poll();
if (node.left!=null) queue.add(node.left);
if (node.right!=null) queue.add(node.right);
}
}
return res;
}
}
复杂度分析:
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)
递归代码:递归的代码理解为前中后序都可以,因为实际没有中序的逻辑;递归三部曲:1、传入参数:当前结点及当前节点的深度;2、终止条件:当当前节点为空的时候终止;3、单层逻辑:当当前深度大于最大深度的时候,更新最大深度和res的值,然后进行左右递归,注意,这里必须先进行左递归,因为最后的res的值可能出现在左节点上,也可能出现在右节点上,这样的目的是保证如果最后一层左节点在最左边,那么结果一定是它的值!!!
class Solution {
int res,maxdepth;
public int findBottomLeftValue(TreeNode root) {
dfs(root,1);
return res;
}
public void dfs(TreeNode node,int depth){
if (node==null) return;
//如果当前深度大于最大深度,改变res的值
if (depth>maxdepth){
maxdepth = depth;
res = node.val;
}
//这里必须先进行左递归!!!
//这里的传入参数是depth+1,起始隐藏这回溯的逻辑
dfs(node.left,depth+1);
dfs(node.right,depth+1);
}
}
复杂度分析:
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)
题目链接: 路径总和
自己的思路:不会!!!自己写的只能过百分之五十的例子!!!主要是终止条件没有设置好!!!
正确思路:递归三部曲:1、传入参数:当前节点和当前剩余的和(减完);2、终止条件:当当前结点为空的时候,返回false,如果当前结点是叶子结点,而且当前结点的值和剩余的和的值相等,返回true,否则返回false;3、单层递归:分别向左和向右递归,并且用或运算连接!!!!
代码:
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
//终止条件
if (root==null) return false;
if (root.left==null&&root.right==null){
//正好把sum减为0
return root.val==targetSum;
}
//单层递归逻辑
return hasPathSum(root.left,targetSum-root.val)||hasPathSum(root.right,targetSum-root.val);
}
}
复杂度分析:
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)
题目链接: 路径总和 II
自己的思路:res.add()那里使用的res.add(path),一直得不到想要的结果
正确思路:递归三部曲:1、传入参数:当前节点,剩余的和;2、终止条件:碰到空节点或者叶子节点,如果碰到叶子节点,并且满足路径之和等于sum,将路径加入到res中(因为是值传递,所以要new一个新的对象),然后回溯,返回,否则直接回溯返回;3、单层逻辑:左右进行递归,然后回溯当前节点!!!!
代码:
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
dfs(root,targetSum);
return res;
}
public void dfs(TreeNode node,int target){
if (node==null) return;
path.add(node.val);
//当碰到叶子节点时
if (node.left==null&&node.right==null){
//将符合条件的路径加入到res中
if (target==node.val) res.add(new ArrayList(path));
//回溯
path.remove(path.size()-1);
return;
}
dfs(node.left,target-node.val);
dfs(node.right,target-node.val);
//回溯
path.remove(path.size()-1);
}
}
复杂度分析:
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)
题目链接: 从中序与后序遍历序列构造二叉树
自己的思路:想到如何去构建,但是不会写代码!!!!
正确思路:给定了中序遍历左中右和后序遍历左右中,如果想构造出二叉树来,那么一定要找到后序遍历的最后一个节点,通过这个节点来拆分中序遍历的左右子树,然后拆分出中序遍历的左右子树,通过左右子树的长度进而确定后序遍历中的左右子树即可!!递归三部曲:1、传入参数:前序遍历左(右)子树的起始点和终止点,后序遍历左(右)子树的起始点和终止点;2、终止条件:当数组不成立时即返回;3、单层逻辑:先找后序遍历的最后一个节点,通过这个节点找中序遍历的根结点,然后左右递归即可!!
代码:
class Solution {
//构造一个map用于存放中序遍历中各个结点值和其索引
Map<Integer,Integer> map = new HashMap<>();
//后序遍历
int[] post;
public TreeNode buildTree(int[] inorder, int[] postorder) {
for (int i =0;i<inorder.length;i++) map.put(inorder[i],i);
post = postorder;
TreeNode root = buildTree(0,inorder.length-1,0,postorder.length-1);
return root;
}
public TreeNode buildTree(int il,int ir,int pl,int pr){
if (ir<il||pr<pl) return null;
//找到后序遍历中最后一个节点的值
int pnode = post[pr];
//去中序中寻找索引
int inode = map.get(pnode);
TreeNode node = new TreeNode(pnode);
//递归左右子树
node.left = buildTree(il,inode-1,pl,pl+inode-1-il);
node.right = buildTree(inode+1,ir,pl+inode-il,pr-1);
return node;
}
}
复杂度分析:
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)
题目链接: 从前序与中序遍历序列构造二叉树
自己的思路:会上一个就会这一个,基本一模一样!!!!!
正确思路:
代码:
class Solution {
Map<Integer,Integer> map = new HashMap<>();
int[] pre;
public TreeNode buildTree(int[] preorder, int[] inorder) {
for (int i =0;i<inorder.length;i++) map.put(inorder[i],i);
pre = preorder;
TreeNode root = buildTree(0,inorder.length-1,0,preorder.length-1);
return root;
}
public TreeNode buildTree(int il,int ir,int pl,int pr){
if (ir<il||pr<pl) return null;
int pnode = pre[pl];
int inode = map.get(pnode);
TreeNode root = new TreeNode(pnode);
root.left = buildTree(il,inode-1,pl+1,pl+inode-il);
root.right = buildTree(inode+1,ir,pl+inode-il+1,pr);
return root;
}
}
复杂度分析:
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)