Day18题目
LeetCode513.找树最底层最左边的值
核心思想:用层序遍历很简单,只要找最后一层的第一个就行了。使用递归的话,维护一个深度,当遇到更深的节点的时候更新一次(同一深度不更新),注意要让左子树先遍历。这里提供递归代码。
class Solution {
// 当有节点深度大于此值的时候就把它赋给res
int maxDepth = 0;
int res = 0;
public int findBottomLeftValue(TreeNode root) {
// 递归
help(root,1);
return res;
}
public void help(TreeNode root,int depth){
if(root == null) return;
// 一定要先左!!
help(root.left,depth+1);
if(depth > maxDepth){
maxDepth = depth;
res = root.val;
}
help(root.right,depth+1);
}
}
LeetCode 112.路经总和:是否有从根节点到叶子节点和为target的路径
核心思想:回溯。维护一个sum,遍历完子节点记得回溯。
class Solution {
int sum = 0;
// 维护结果,有一条就是true
boolean res = false;
public boolean hasPathSum(TreeNode root, int targetSum) {
// 遍历所有的路径
help(root,targetSum);
return res;
}
public void help(TreeNode root,int targetSum){
if(root == null) return;
// 在判断sum是否等于target之前先加上节点的值。
sum += root.val;
// 除了值一样,还要判断是否是叶子节点
if(sum == targetSum && root.left == null && root.right == null ){
res = true;
}
if(root.left != null){
help(root.left,targetSum);
// 遍历完左节点要回溯sum,保证遍历右节点前值是正确的
sum = sum-root.left.val;
}
if(root.right != null){
help(root.right,targetSum);
// 同理回溯,保证父节点的父节点遍历下一个节点之前,值是正确的
sum = sum-root.right.val;
}
}
}
LeetCode 113.路径之和Ⅱ:需要返回所有路径的具体值
核心思想:和112一样,回溯,只不过多维护一个path数组,存放目前为止的节点值,回溯sum的时候一并回溯。注意:res添加path的时候要写 new ArrayList(path);
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
int sum = 0;
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
sum = 0;
path = new ArrayList<>();
res = new ArrayList<>();
help(root,targetSum);
return res;
}
public void help(TreeNode root,int targetSum){
if(root == null) return;
sum += root.val;
path.add(root.val);
if(sum == targetSum && root.left == null && root.right == null){
// 这块注意!!!
res.add(new ArrayList(path));
}
if(root.left != null){
help(root.left,targetSum);
// 回溯sum和path
sum -= root.left.val;
path.removeLast();
}
if(root.right != null){
help(root.right,targetSum);
// 回溯
sum -= root.right.val;
path.removeLast();
}
}
}
LeetCode 105. 从前序与中序遍历序列构造二叉树
核心思想:递归,以及看着某一个实例写代码,否则对边界会想乱。这里提供最容易看明白的切割数组的方式,可以使用边界来模拟切割数组,快得多。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
// 前序 根左右
// 中序 左根右
// 1.获取根
if(preorder.length == 0) return null;
TreeNode root = new TreeNode(preorder[0]);
// 2.从中序找到根节点的index
int index = 0;
for(;index < inorder.length; index ++){
if(inorder[index] == root.val){
break;
}
}
// 3.以index 切割数组,包含左边界,不包含右边界
int[] leftInorder = Arrays.copyOfRange(inorder,0,index);
int[] rightInorder = Arrays.copyOfRange(inorder, index+1, inorder.length);
// 从第二个元素开始,一共有leftInorder 长度个元素,而且切割不包含右边界,那么下标就到了1+length
int[] leftPreorder = Arrays.copyOfRange(preorder,1,leftInorder.length+1);
int[] rightPreorder = Arrays.copyOfRange(preorder,leftInorder.length+1,preorder.length);
root.left = buildTree(leftPreorder,leftInorder);
root.right = buildTree(rightPreorder,rightInorder);
return root;
}
}
// 边界条件
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return help(preorder, inorder, 0, preorder.length, 0, inorder.length);
}
public TreeNode help(int[] preorder, int[] inorder, int preorderBegin, int preorderEnd, int inorderBegin, int inorderEnd) {
if (preorderBegin >= preorderEnd || inorderBegin >= inorderEnd) return null;
TreeNode root = new TreeNode(preorder[preorderBegin]);
int index = inorderBegin;
for (; index < inorderEnd; index++) {
if (inorder[index] == root.val) {
break;
}
}
// 计算左子树的长度
int leftLength = index - inorderBegin;
// 构建左子树
root.left = help(preorder, inorder, preorderBegin + 1, preorderBegin + 1 + leftLength, inorderBegin, index);
// 构建右子树
root.right = help(preorder, inorder, preorderBegin + 1 + leftLength, preorderEnd, index + 1, inorderEnd);
return root;
}
}
LeetCode106. 从中序与后序遍历序列构造二叉树
核心思想:和105同理,保持清晰头脑,确定好边界情况
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
// 中序:左中右
// 后序:左右中
// 1.先从后序找中
if(postorder.length == 0) return null;
TreeNode root = new TreeNode(postorder[postorder.length-1]);
// 2.在中序中找root的位置
int index = 0;
for(; index<inorder.length; index ++){
if(inorder[index] == root.val){
break;
}
}
// index 是 root 的下标
// 切割inorder数组 包含左边界,不包含右边界
int[] leftInorder = Arrays.copyOfRange(inorder,0,index);
int[] rightInorder = Arrays.copyOfRange(inorder,index+1,inorder.length);
// 切割postOrder数组
int[] leftPostorder = Arrays.copyOfRange(postorder,0,leftInorder.length);
int[] rightPostorder = Arrays.copyOfRange(postorder,leftInorder.length,postorder.length-1);
root.left = buildTree(leftInorder,leftPostorder);
root.right = buildTree(rightInorder,rightPostorder);
return root;
}
}
2248



被折叠的 条评论
为什么被折叠?



