513.找树左下角的值
本地递归偏难,反而迭代简单属于模板题, 两种方法掌握一下
左侧节点不一定是左孩子
可以使用前序遍历(当然中序,后序都可以)优先遍历左侧 左侧没有就去找右侧了
class Solution {
public int Deep=-1;
public int res=0;//用来记录每一层的第一个值 即最左侧的值
public int findBottomLeftValue(TreeNode root) {
res=root.val;
findLeftValue(root,0);//更改res的值 所以返回void就可以
return res;
}
public void findLeftValue(TreeNode root,int deep){
if(root==null) return;
if(root.left==null&&root.right==null){
if(deep>Deep){
res=root.val;
Deep=deep; //不可以Deep++,因为有递归不是每一层都能按顺序++,但是deep是按照顺序++
}
}
if (root.left != null) findLeftValue(root.left,deep+1);//不可以用deep++!!!!!!!!!!
if (root.right != null) findLeftValue(root.right,deep+1);
}
}
迭代法
class Solution {
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
int res=root.val;
while(!queue.isEmpty()){//一次while循环是一层
int size=queue.size();//记录一下每轮这一层的数量
for(int i=0;i<size;i++){//记录当前层的最左侧值,并按照这一层的数量往队列里放入下一层的值(for循环)
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;
}
}
- 路径总和
本题 又一次设计要回溯的过程,而且回溯的过程隐藏的还挺深,建议先看视频来理解
没有中的处理逻辑的话 前中后序都可以
这里用中序
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;//返回最后目标值是否减为0
}
if(root.left!=null){
// return hasPathSum(root.left, targetSum);
boolean left = hasPathSum(root.left, targetSum);
if (left) { // 已经找到
return true;
}
}
if(root.right!=null){
// return hasPathSum(root.right, targetSum);//不对!!!!没找到也返回了就不会继续找了
boolean right = hasPathSum(root.right, targetSum);
if (right) { // 找到了才返回,没找到不返回
return true;
}
}
return false;//以上都没找到才会运行
}
}
- 路径总和,和 113. 路径总和ii 一起做了。 优先掌握递归法。
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> paths=new ArrayList<>();
findPath(root,res,paths,targetSum);//找到path放到res中
return res;
}
public void findPath(TreeNode root, List<List<Integer>> res, List<Integer> paths, int targetSum){
if(root==null) return;
paths.add(root.val);
targetSum-=root.val;
if(root.right==null&&root.left==null){
if(targetSum==0){
res.add(new ArrayList<>(paths));//必须这么做!!(看图片)
}
return;
}
if(root.left!=null){
findPath(root.left,res,paths,targetSum);
paths.remove(paths.size() - 1); // 回溯
}
if(root.right!=null){
findPath(root.right,res,paths,targetSum);
paths.remove(paths.size() - 1); // 回溯
}
}
}
106.从中序与后序遍历序列构造二叉树
(别看代码随想录的答案)
本题算是比较难的二叉树题目了,大家先看视频来理解。
每次从中序遍历中找到中间节点去切割前序遍历
class Solution {
int post_idx;
int[] postorder;
int[] inorder;
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
//
this.postorder = postorder;
this.inorder = inorder;
// 从后序遍历的最后一个元素开始
post_idx = postorder.length - 1;
// 建立(元素,下标)键值对的哈希表 元素是key 下标是value
int idx = 0;
for (Integer val : inorder) {
map.put(val, idx++);
}
return helper(0, inorder.length - 1);
}
public TreeNode helper(int in_left, int in_right) {
// 如果这里没有节点构造二叉树了,就结束
if (in_left > in_right) {
return null;
}
// 选择 post_idx 位置的元素作为当前子树根节点
int root_val = postorder[post_idx];
TreeNode root = new TreeNode(root_val);
// 根据 root 所在位置将前序分成左右两棵子树
int in_root_index = map.get(root_val);
// 下标减一
post_idx--;
// 构造右子树
root.right = helper(in_root_index + 1, in_right);
// 构造左子树
root.left = helper(in_left, in_root_index - 1);
return root;
}
}
106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树 一起做,思路一样的
105.从前序与中序遍历序列构造二叉树
class Solution {
int pre_idx;
int[] preorder;
int[] inorder;
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
//
this.preorder = preorder;
this.inorder = inorder;
// 从前序遍历的第一个元素开始
pre_idx = 0;
// 建立中序(元素,下标)键值对的哈希表 元素是key 下标是value 用元素找下表
int idx = 0;
for (Integer val : inorder) {
map.put(val, idx++);
}
return helper(0, inorder.length - 1);
}
public TreeNode helper(int in_left, int in_right) {
// 如果这里没有节点构造二叉树了,就结束
if (in_left > in_right) {
return null;
}
// 选择 前序遍历中的pre_idx 位置的元素作为当前子树根节点
int root_val = preorder[pre_idx];//
TreeNode root = new TreeNode(root_val);
// 根据 root_val 所在位置将前序分成左右两棵子树
int in_root_index = map.get(root_val);
// 下标++
pre_idx++;
// 构造左子树
root.left = helper(in_left, in_root_index - 1);
// 构造右子树
root.right = helper(in_root_index + 1, in_right);
return root;
}
}