Leetcode 513. 找树左下角的值
题目链接:513. 找树左下角的值
本题适合用层序遍历,比递归要好理解。本题涉及递归求深度的写法。
代码实现(递归)
class Solution {
int maxDepth = Integer.MIN_VALUE;
int result = 0;
public int findBottomLeftValue(TreeNode root) {
dfs(root, 0);
return result;
}
public void dfs(TreeNode root, int depth){
if(root.left == null && root.right == null && depth > maxDepth){
maxDepth = depth;
result = root.val;
return;
}
if(root.left != null){
dfs(root.left, depth + 1);
}
if(root.right != null){
dfs(root.right, depth + 1);
}
}
}
Leetcode 112. 路径总和
题目链接:112. 路径总和
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null){
return false;
}
return dfs(root, targetSum - root.val);
}
//其实这个递归函数可以和主函数合并
public boolean dfs(TreeNode root, int sum){
if(root.left == null && root.right == null){
return sum == 0;
}
if(root.left != null){
if(dfs(root.left, sum - root.left.val)){
return true;
}
}
if(root.right != null){
if(dfs(root.right, sum - root.right.val)){
return true;
}
}
return false;
}
}
Leetcode 113. 路径总和 II
题目链接:113. 路径总和 II
通过本题和上一题,可以了解递归函数什么时候需要返回值,什么时候不需要。
class Solution {
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if(root == null){
return result;
}
List<Integer> path = new ArrayList<>();
path.add(root.val);
dfs(root, targetSum - root.val, path);
return result;
}
public void dfs(TreeNode root, int sum, List<Integer> path){
if(root.left == null && root.right == null){
if(sum == 0){
List<Integer> tmp = new ArrayList<>(path);
result.add(tmp);
}
return;
}
if(root.left != null){
path.add(root.left.val);
dfs(root.left, sum - root.left.val, path);
path.remove(path.size() - 1);
}
if(root.right != null){
path.add(root.right.val);
dfs(root.right, sum - root.right.val, path);
path.remove(path.size() - 1);
}
}
}
Leetcode 106. 从中序与后序遍历序列构造二叉树
题目链接:106. 从中序与后序遍历序列构造二叉树
有点难度。
如何根据两个顺序构造一个唯一的二叉树?就是以后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
return dfs(inorder, 0, inorder.length, postorder, 0 ,postorder.length);
}
//遵循左闭右开
public TreeNode dfs(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd){
if(postBegin >= postEnd){
return null;
}
int rootVal = postorder[postEnd - 1];
TreeNode root = new TreeNode(rootVal);
if(postorder.length == 1){
return root;
}
int middleIndex = inBegin;
for(middleIndex = inBegin; middleIndex < inEnd; middleIndex++){
if(inorder[middleIndex] == rootVal){
break;
}
}
int leftInBegin = inBegin;
int leftInEnd = middleIndex;
int rightInBegin = middleIndex + 1;
int rightInEnd = inEnd;
int leftPostBeigin = postBegin;
int leftPostEnd = postBegin + (leftInEnd - leftInBegin);
int rightPostBegin = leftPostEnd;
int rightPostEnd = postEnd - 1;
root.left = dfs(inorder, leftInBegin, leftInEnd, postorder, leftPostBeigin, leftPostEnd);
root.right = dfs(inorder, rightInBegin, rightInEnd, postorder, rightPostBegin, rightPostEnd);
return root;
}
}
Leetcode 105. 从前序与中序遍历序列构造二叉树
题目链接:105. 从前序与中序遍历序列构造二叉树
本题和Leetcode 106是一样的逻辑。
前序和中序可以唯一确定一棵二叉树。
后序和中序可以唯一确定一棵二叉树。
**前序和后序不能唯一确定一棵二叉树。**因为没有中序遍历,无法确定左右部分,也就是无法分割。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return dfs(inorder, 0, inorder.length, preorder, 0 ,preorder.length);
}
//遵循左闭右开
public TreeNode dfs(int[] inorder, int inBegin, int inEnd, int[] preorder, int preBegin, int preEnd){
if(preBegin >= preEnd){
return null;
}
int rootVal = preorder[preBegin];
TreeNode root = new TreeNode(rootVal);
if(preorder.length == 1){
return root;
}
int middleIndex = inBegin;
for(middleIndex = inBegin; middleIndex < inEnd; middleIndex++){
if(inorder[middleIndex] == rootVal){
break;
}
}
int leftInBegin = inBegin;
int leftInEnd = middleIndex;
int rightInBegin = middleIndex + 1;
int rightInEnd = inEnd;
int leftPreBeigin = preBegin + 1;
int leftPreEnd = leftPreBeigin + (leftInEnd - leftInBegin);
int rightPreBegin = leftPreEnd;
int rightPreEnd = preEnd;
root.left = dfs(inorder, leftInBegin, leftInEnd, preorder, leftPreBeigin, leftPreEnd);
root.right = dfs(inorder, rightInBegin, rightInEnd, preorder, rightPreBegin, rightPreEnd);
return root;
}
}
P.S. 还可以进一步优化:用一个Map,key保存inorder的数值,value保存数值对应的inorder数组下标,这样每次递归时就不用for循环查找middleIndex。