513.找树左下角的值
- 题目链接:代码随想录
- 解题思路:
递归法:
①确定参数,要携带每层处理结点和高度,不需要返回值
②全局参数:需要记录结果集和初始化最大深度
③终止条件:遍历到叶子结点为止
④处理逻辑:当遍历到叶子结点就比较深度,看看是否是最大深度;没遍历到就继续遍历
public class Solution {
public int result;
public int maxDeep = -1;
public int findBottomLeftValue(TreeNode root) {
traversal(root,0);
return result;
}
private void traversal(TreeNode root,int deep){
//直接前序遍历,终止条件
if(root.left == null && root.right == null){
if(deep > maxDeep){
maxDeep = deep;
result = root.val;
}
return ;
}
//开始遍历左子树和右子树
if(root.left != null){
deep++;
traversal(root.left, deep);
//回溯,回到这一层
deep--;
}
if(root.right != null){
deep++;
traversal(root.right, deep);
//回溯,回到这一层
deep--;
}
}
}
class SolutionByTwo{
/**
* 迭代法求解
* 用到层序遍历的思路:
* 存取第一个的逻辑是每层更新第一个,直到遍历到最后一层
* @param root
* @return
*/
public int findBottomLeftValue(TreeNode root) {
//存取每一层数据
Deque<TreeNode> deque = new LinkedList<TreeNode>();
int result = -1;
int flag = 0;
deque.addLast(root);
while(!deque.isEmpty()){
int len = deque.size();
//每层的逻辑
while((len--) > 0){
TreeNode temp = deque.removeFirst();
if(flag == 0){
result = temp.val;//每次取第一个值
flag = 1;
}
if(temp.left != null){
deque.addLast(temp.left);
}
if(temp.right != null){
deque.addLast(temp.right);
}
}
flag = 0;
}
return result;
}
}
112. 路径总和 113.路径总和ii
题目链接:代码随想录
-
本题前中后序都可以,无所谓,因为中节点也没有处理逻辑
-
递归法解题思路:
①确定参数:参数应该为要处理的节点和临时和,还有比对的目标值
②终止条件:遍历到叶子结点结束,判断叶子结点是不是目标和,将结果存取到固定目标集中
③处理逻辑:如果不是叶子结点,就加上当前值,然后进入下一层递归;递归完之后进行回溯
public class Solution1 {
public int result = 0;//当结果为1的时候说明为目标和,直接返回
public boolean hasPathSum(TreeNode root, int targetSum) {
traversal(root,0,targetSum);
return result == 1;
}
public void traversal(TreeNode root,int sum,int target){//这里sum一定要声明为栈变量,不要声明为全局
if(root.left == null && root.right == null){
//处理逻辑
if(sum + root.val == target){
result = 1;
}
return;
}
//处理左右子树
if(root.left != null && result != 1){//result != 1进行剪枝操作
sum += root.val;
traversal(root.left, sum, target);
//回溯
sum -= root.val;
}
if(root.right != null && result != 1){//result != 1进行剪枝操作
sum += root.val;
traversal(root.right, sum, target);
//回溯
sum -= root.val;
}
}
}
- 解题思路:
和搜索路径一解题思路类似,就是这个题不能再剪枝,要考虑到每一种情况
做题语法注意点:result.add(new ArrayList<>(path));这里一定要new 一个数组,要不最终存的都是path的引用,也不是正确值
public class Solution2 {
public 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<>();
traversal(root,path,targetSum);
return result;
}
public void traversal(TreeNode root,List<Integer> path,int target){
path.add(root.val);
if(root.left == null && root.right == null){
//处理逻辑
int sum = 0;
for(int i = 0;i < path.size();i++){
sum += path.get(i);
}
if(sum == target){
result.add(new ArrayList<>(path));这里一定要new 一个数组,要不最终存的都是path的引用,也不是正确值
}
return;
}
//处理左右子树
if(root.left != null){
traversal(root.left, path, target);
//回溯
path.remove(path.size() - 1);
}
if(root.right != null){
traversal(root.right, path, target);
//回溯
path.remove(path.size() - 1);
}
}
}
106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树
题目链接:代码随想录
-
解题思路:
第一步:如果数组大小为零的话,说明是空节点了。
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
第五步:切割后序数组,切成后序左数组和后序右数组
第六步:递归处理左区间和右区间题难点在于切割二叉树
public class Solution3 {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder == null || postorder == null){return null;}
return traversal(inorder,postorder);
}
private TreeNode traversal(int[] inorder, int[] postorder) {
//数组大小为0,说明是空节点
if(postorder.length == 0) {return null;}
//后序遍历节点的最后一个节点是当前中间节点
int rootValue = postorder[postorder.length - 1];
TreeNode root = new TreeNode(rootValue);
//如果后序数组只有一个元素那么直接返回即可
if(postorder.length == 1){return root;}
//确定中序分割点
int delimiterIndex;
for(delimiterIndex = 0;delimiterIndex < inorder.length;delimiterIndex++){
if(inorder[delimiterIndex] == rootValue){
break;
}
}
//切割中序数组
int[] leftInorder = Arrays.copyOfRange(inorder, 0,delimiterIndex);
int[] rightInorder = Arrays.copyOfRange(inorder, delimiterIndex + 1,inorder.length);
//切割后序数组
// [0, leftInorder.size)
int[] leftPostorder = Arrays.copyOfRange(postorder, 0,leftInorder.length);
// [leftInorder.size(), postorder.length - 1)
int[] rightPostorder = Arrays.copyOfRange(postorder, leftInorder.length,postorder.length - 1);
root.left = traversal(leftInorder, leftPostorder);
root.right = traversal(rightInorder, rightPostorder);
return root;
}
}
// [leftInorder.size(), postorder.length - 1)
int[] rightPostorder = Arrays.copyOfRange(postorder, leftInorder.length,postorder.length - 1);
root.left = traversal(leftInorder, leftPostorder);
root.right = traversal(rightInorder, rightPostorder);
return root;
}
}