513.找树左下角的值
- 刷题
https://leetcode.cn/problems/find-bottom-left-tree-value/description/
- 文章讲解
https://programmercarl.com/0513.%E6%89%BE%E6%A0%91%E5%B7%A6%E4%B8%8B%E8%A7%92%E7%9A%84%E5%80%BC.html
- 视频讲解
https://www.bilibili.com/video/BV1424y1Z7pn/?vd_source=af4853e80f89e28094a5fe1e220d9062
-
题解1(迭代法):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//迭代法
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int result = 0;
while(!queue.isEmpty()){
//记录当前遍历层的元素的个数,保证层序遍历
int size = queue.size();
for(int i = 0;i < size;i ++){
//弹出队首元素
TreeNode cur = queue.poll();
//用result记录i==1即当前层的首元素
//随着遍历层数增加而不断更新迭代每一层的首元素
//直到更新为最后一层的首元素,遍历完成
if(i == 0){
result = cur.val;
}
//若存在则加入弹出元素的左孩子
if(cur.left != null){
queue.offer(cur.left);
}
//若存在则加入弹出元素的右孩子
if(cur.right != null){
queue.offer(cur.right);
}
}
}
return result;
}
}
-
题解2(递归法):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//递归法
//记录当前最大深度
int DEEP = -1;
//记录当前最大深度结点
int value = 0;
public int findBottomLeftValue(TreeNode root) {
value = root.val;
findLeftValue(root, 0);
return value;
}
public void findLeftValue(TreeNode root,int deep){
//递归出口
if(root == null){
return;
}
//若遍历到叶子结点且该结点深度为目前最大,则更新DEEP和value
if(root.left == null && root.right == null){
if(deep > DEEP){
value = root.val;
DEEP = deep;
}
}
//左处理
if(root.left != null){
deep += 1;
//递归
findLeftValue(root.left, deep);
//回溯
deep -= 1;
//此三行的简写形式
// findLeftValue(root.left, deep + 1);
}
//右处理
if(root.right != null){
deep += 1;
findLeftValue(root.right, deep);
deep -= 1;
//此三行的简写形式
// findLeftValue(root.right, deep + 1);
}
}
}
112. 路径总和
- 刷题
https://leetcode.cn/problems/path-sum/description/
- 文章讲解
https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html
- 视频讲解
https://www.bilibili.com/video/BV19t4y1L7CR/?vd_source=af4853e80f89e28094a5fe1e220d9062
-
题解(递归法):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//递归
List<List<Integer>> result;
LinkedList<Integer> path;
public boolean hasPathSum(TreeNode root, int targetSum) {
result = new LinkedList<>();
path = new LinkedList<>();
travesal(root, targetSum);
return !result.isEmpty();
}
public void travesal(TreeNode root, int count){
//递归结束返回
if(root == null){
return;
}
//路径中加入根结点
path.offer(root.val);
//处理加入结点的值
count -= root.val;
//若在某条路径中到叶子结点时count已经减为0,
//则说明这条路路径总和符合要求
if(root.left == null && root.right == null && count == 0){
//将当前path路径列表加入最终结果列表
result.add(new LinkedList<>(path));
}
//递归处理
//左处理
travesal(root.left, count);
//右处理
travesal(root.right, count);
//回溯处理
path.removeLast();
//中无需处理,因为不对中操作
}
}
113.路径总和ii
- 刷题
https://leetcode.cn/problems/path-sum-ii/description/
- 文章讲解
https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html
- 视频讲解
https://www.bilibili.com/video/BV19t4y1L7CR/?vd_source=af4853e80f89e28094a5fe1e220d9062
-
题解(递归法):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//递归
List<List<Integer>> result;
// LinkedList作为Queue的实现类使用offer方法
LinkedList<Integer> path;
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
result = new LinkedList<>();
path = new LinkedList<>();
travesal(root, targetSum);
return result;
}
public void travesal(TreeNode root, int targetSum){
if(root == null){
return;
}
path.offer(root.val);
targetSum -= root.val;
if(root.left == null && root.right == null && targetSum == 0){
result.add(new LinkedList<>(path));
}
travesal(root.left, targetSum);
travesal(root.right, targetSum);
path.removeLast();
}
}
106.从中序与后序遍历序列构造二叉树
- 刷题
https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
- 文章讲解
https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E%84%E9%80%A0%E4%BA%8C%E5%8F%89%E6%A0%91.html
- 视频讲解
https://www.bilibili.com/video/BV1vW4y1i7dn/?vd_source=af4853e80f89e28094a5fe1e220d9062
-
题解(递归法):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//中序后序构造二叉树
//使用Map结构,方便根据数值查找位置
Map<Integer, Integer> map;
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<>();
//使用Map存储中序序列数值
for(int i = 0; i < inorder.length; i++){
//注意map存储结构:
//key键为中序序列的元素本身,value值为中序序列元素的下标
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;
}
//步骤1:找到后序遍历最后一个元素在中序遍历中的位置,对中序遍历做切割
//获取当前根结点在中序序列中对应的下标
int rootIndex = map.get(postorder[postEnd - 1]);
//用中序遍历的中结点构造出新二叉树的根结点
TreeNode root = new TreeNode(inorder[rootIndex]);
//步骤2:用中序遍历切割后的中序前半序列的长度对后序遍历序列做切割
//获得中序前半序列的长度
int lenOfLeft = rootIndex - inBegin;
//步骤3:用中序序列切割后的前半序列和后序序列切割后的前半序列进行再一次的递归
//下同,用中序序列切割后的后半序列和后序序列切割后的后半序列进行再一次的递归
root.left = findNode(inorder, inBegin, rootIndex,
postorder, postBegin, postBegin + lenOfLeft);
//debug点:这里的容器为左闭右开,需要根据左闭右开设置递归边界
//为保证序列连续性,inorder开始需要+1
//postEnd - 1,加上左闭右开,因为要空出来这一趟后序遍历挑出来的root切割点
//中序遍历的切割点也通过rootIndex和rootIndex + 1的左闭右开设置在rootIndex位置做了切割
root.right = findNode(inorder, rootIndex + 1, inEnd,
postorder, postBegin + lenOfLeft, postEnd - 1);
//步骤4:root结点已定义,root.left,root.right均已通过递归确定,
//可以返回root代表重新构建的二叉树
return root;
}
}
105.从前序与中序遍历序列构造二叉树
- 刷题
https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/
- 文章讲解
https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E%84%E9%80%A0%E4%BA%8C%E5%8F%89%E6%A0%91.html
- 视频讲解
https://www.bilibili.com/video/BV1vW4y1i7dn/?vd_source=af4853e80f89e28094a5fe1e220d9062
-
题解(递归法)
(目前执行出错,错误信息如下)
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 5
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//前序中序遍历序列构造二叉树
Map<Integer, Integer> map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
map = new HashMap<>();
for(int i = 0; i < inorder.length; i++){
//键、值,依然从中序序列中提取新二叉树的元素
map.put(inorder[i], i);
}
return findNode(preorder, 0, preorder.length, inorder, 0, inorder.length);
}
public TreeNode findNode(int[] preorder, int preBegin, int preEnd, int[] inorder, int inBegin, int inEnd){
//递归出口(左闭右开)
if(inBegin >= inEnd || preBegin >= preEnd){
return null;
}
//步骤1:根据前序遍历确定root来切割中序序列
int rootIndex = map.get(preorder[preBegin]);
//存储这一轮找出的根结点
TreeNode root = new TreeNode(inorder[rootIndex]);
//步骤2:用前序序列切割出来的前半序列的长度对中序序列进行切割
int lenOfLeft = rootIndex - inBegin;
//步骤3:递归root的左孩子和右孩子(左闭右开)
//挖去当前根结点,对左右子树进行处理
root.left = findNode(preorder, preBegin + 1, preBegin + lenOfLeft,
inorder, inBegin, rootIndex);
root.right = findNode(preorder, preBegin + lenOfLeft, preEnd,
inorder, rootIndex + 1, inEnd);
return root;
}
}
-
题解(递归法):
(Bug已解决,原因:由于前序序列已经确定出root,所以preBegin和preEnd都应该向后加一)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
//前序中序遍历序列构造二叉树
Map<Integer, Integer> map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
map = new HashMap<>();
for(int i = 0; i < inorder.length; i++){
//键、值,依然从中序序列中提取新二叉树的元素
map.put(inorder[i], i);
}
return findNode(preorder, 0, preorder.length, inorder, 0, inorder.length);
}
public TreeNode findNode(int[] preorder, int preBegin, int preEnd, int[] inorder, int inBegin, int inEnd){
//递归出口(左闭右开)
if(inBegin >= inEnd || preBegin >= preEnd){
return null;
}
//步骤1:根据前序遍历确定root来切割中序序列
int rootIndex = map.get(preorder[preBegin]);
//存储这一轮找出的根结点
TreeNode root = new TreeNode(inorder[rootIndex]);
//步骤2:用前序序列切割出来的前半序列的长度对中序序列进行切割
int lenOfLeft = rootIndex - inBegin;
//步骤3:递归root的左孩子和右孩子(左闭右开)
//挖去当前根结点,对左右子树进行处理
//debug点:由于前序序列已经确定出root,所以preBegin和preEnd都应该向后加一
root.left = findNode(preorder, preBegin + 1, preBegin + lenOfLeft + 1,
inorder, inBegin, rootIndex);
root.right = findNode(preorder, preBegin + lenOfLeft + 1, preEnd,
inorder, rootIndex + 1, inEnd);
return root;
}
}