513.找树左下角的值
题目:513. 找树左下角的值 - 力扣(LeetCode)
思路:层序遍历,找到最后一层,然后弹出第一个值,怎么确定是最后一层?用ArrayList存,存完先求size,再get(size - 1)
层序遍历(AC)
class Solution {
public int findBottomLeftValue(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
List<Integer> list = new ArrayList<>();
int size = que.size();
while(size>0){
TreeNode temp = que.poll();
list.add(temp.val);
if(temp.left!=null) que.offer(temp.left);
if(temp.right!=null) que.offer(temp.right);
size--;
}
res.add(list);
}
int len = res.size();
List<Integer> result = res.get(len - 1);
return result.get(0);
}
}
答案
迭代法
//迭代法
class Solution {
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
int res = 0;
while(!que.isEmpty()){
int size = que.size();
for(int i = 0; i < size; i++){
TreeNode temp = que.poll();
if(i == 0) res = temp.val;
if(temp.left!=null) que.offer(temp.left);
if(temp.right!=null) que.offer(temp.right);
}
}
return res;
}
}
递归法
class Solution {
private int maxDeep= -1;
private int value = 0;
public int findBottomLeftValue(TreeNode root) {
value = root.val;
findLeftValue(root,0);
return value;
}
private void findLeftValue (TreeNode root,int deep) {
if (root == null) return;
if (root.left == null && root.right == null) {
if (deep > maxDeep) {
value = root.val;
maxDeep= deep;
}
}
if (root.left != null) findLeftValue(root.left,deep + 1);
if (root.right != null) findLeftValue(root.right,deep + 1);
}
}
小结
🍉层序遍历的关键是队列!——我的思路是,遍历后的内容都存起来,全部遍历完再取出。卡尔的迭代法,直接用一个队列,找队列里的第一个,因为队列空的时候就是在最后一行。
🍉递归的关键深度和隐藏的回溯,下面两个代码效果是一样的
if (root.left != null) findLeftValue(root.left,deep + 1);
if (root.left != null) {
deep++;
findLeftValue(root.left,deep);
deep--;
}
🍉递归三步曲
1、参数:当前节点,深度;返回值:void
2、终止条件:遇到叶子节点,就对比当前深度与最大深度,更新叶子节点
3、处理逻辑: 控制回溯,注意要先左后右,因为这样遍历到最深一层的左节点之后,res就不会再更新了,也就保证了res是左下角的值
112.路径总和
思路:印象中是用递归+回溯
递归三步曲
1、参数:当前节点,当前路径和,返回值,void
2、终止条件:叶子节点,判断下和是否等于目标值,等于就更新标志位,不等于就返回-1;
3、单层逻辑:
尝试
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
int sum = 0;
return getSum(root,sum) == -1 ? true : false;
}
public int getSum(TreeNode root,int sum){
sum+=root.val;
if(root.left==null && root.right == null){
return sum == targetSum ? -1:0;
}
if(root.left!=null) return getSum(root.left,sum);
if(root.right!=null) return getSum(root.right,sum);
}
}
答案
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false; // 为空退出
// 叶子节点判断是否符合
if (root.left == null && root.right == null) return root.val == targetSum;
// 求两侧分支的路径和
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}
}
小结
🍉我的思路是,路径求和之后再跟目标值比较,卡尔的思路是目标值在路径上不断减少,找到叶子节点,就判断是否为跟目标值累减之后的值相等
106.从中序与后序遍历序列构造二叉树
题目:106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
思路:没有思路,不要说给出我这些信息了,再多给我一个前序遍历序列,我也不知道怎么构造二叉树,按理说,反向构造二叉树,一个序列不就够了吗,关键就是root、left、right每个节点的关系要搞对,
练习
class Solution {
private Map<Integer,Integer> map;
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<>();
for(int i = 0; i < inorder.size(); i++){
map.put(inorder[i],i);
}
int root = postorder[postorder.size()-1];
int rootIndex = map.get(root);
return findNode(inorder,0,inorder.length,postorder,0,postorder.length);
}
public TreeNode findNode(int[] inorder,int inStart,int inEnd, int[] postorder,int postStart,int postEnd){
int lenOfLeft =
}
}
答案
class Solution {
Map<Integer, Integer> map; // 方便根据数值查找位置
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<>();
for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
map.put(inorder[i], i);
}
return findNode(inorder, 0, inorder.length, postorder,0, postorder.length); // 前闭后开
}
public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
// 参数里的范围都是前闭后开
if (inBegin >= inEnd || postBegin >= postEnd) { // 不满足左闭右开,说明没有元素,返回空树
return null;
}
int rootIndex = map.get(postorder[postEnd - 1]); // 找到后序遍历的最后一个元素在中序遍历中的位置
TreeNode root = new TreeNode(inorder[rootIndex]); // 构造结点
int lenOfLeft = rootIndex - inBegin; // 保存中序左子树个数,用来确定后序数列的个数
root.left = findNode(inorder, inBegin, rootIndex,
postorder, postBegin, postBegin + lenOfLeft);
root.right = findNode(inorder, rootIndex + 1, inEnd,
postorder, postBegin + lenOfLeft, postEnd - 1);
return root;
}
}
小结
🍉之所以要中序,后序两个序列,是因为只有后序的话,仅仅是【左右中】无法确定分割位置,加上一个中序【左中右】就能够分开左右
🍉前序+中序,后序+中序,可以构造唯一的二叉树,前序+后序不行,无法确定分割点
🍉先把中序数组存进map里面,方面取出根节点的下标,构造节点