代码随想录-算法训练营day18【二叉树05:找树左下角的值、路径总和、从中序与后序遍历序列构造二叉树】

发布于:2024-04-24 ⋅ 阅读:(22) ⋅ 点赞:(0)

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客

第六章 二叉树 part05
  今日内容 

● 513.找树左下角的值
● 112. 路径总和  113.路径总和ii
● 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树

 详细布置 

 找树左下角的值  

本地递归偏难,反而迭代简单属于模板题, 两种方法掌握一下 

题目链接/文章讲解/视频讲解: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  

 路径总和  

本题 又一次设计要回溯的过程,而且回溯的过程隐藏的还挺深,建议先看视频来理解 

112. 路径总和,和 113. 路径总和ii 一起做了。 优先掌握递归法。

题目链接/文章讲解/视频讲解:https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html  

 从中序与后序遍历序列构造二叉树 

本题算是比较难的二叉树题目了,大家先看视频来理解。 

106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树 一起做,思路一样的

题目链接/文章讲解/视频讲解: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 

往日任务
● day 1 任务以及具体安排:https://docs.qq.com/doc/DUG9UR2ZUc3BjRUdY  
● day 2 任务以及具体安排:https://docs.qq.com/doc/DUGRwWXNOVEpyaVpG  
● day 3 任务以及具体安排:https://docs.qq.com/doc/DUGdqYWNYeGhlaVR6 
● day 4 任务以及具体安排:https://docs.qq.com/doc/DUFNjYUxYRHRVWklp 
● day 5 周日休息
● day 6 任务以及具体安排:https://docs.qq.com/doc/DUEtFSGdreWRuR2p4 
● day 7 任务以及具体安排:https://docs.qq.com/doc/DUElCb1NyTVpXa0Jj 
● day 8 任务以及具体安排:https://docs.qq.com/doc/DUGdsY2JFaFhDRVZH 
● day 9 任务以及具体安排:https://docs.qq.com/doc/DUHVXSnZNaXpVUHN4 
● day 10 任务以及具体安排:https://docs.qq.com/doc/DUElqeHh3cndDbW1Q 
●day 11 任务以及具体安排:https://docs.qq.com/doc/DUHh6UE5hUUZOZUd0 
●day 12 周日休息 
●day 13 任务以及具体安排:https://docs.qq.com/doc/DUHNpa3F4b2dMUWJ3 
●day 14 任务以及具体安排:https://docs.qq.com/doc/DUHRtdXZZSWFkeGdE 
●day 15 任务以及具体安排:https://docs.qq.com/doc/DUHN0ZVJuRmVYeWNv 
●day 16 任务以及具体安排:https://docs.qq.com/doc/DUHBQRm1aSWR4T2NK 
●day 17 任务以及具体安排:https://docs.qq.com/doc/DUFpXY3hBZkpabWFY

目录

0513_找树左下角的值

0112_路径总和

0113_路径总和ii

0106_从中序与后序遍历序列构造二叉树

0105_从前序与中序遍历序列构造二叉树


0513_找树左下角的值

package com.question.solve.leetcode.programmerCarl2._07_binaryTrees;

import java.util.Deque;
import java.util.LinkedList;

public class _0513_找树左下角的值 {
}

/**
 * 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 Solution0513 {
    public int findBottomLeftValue(TreeNode root) {//迭代法
        int res = 0;
        if (root == null) {
            return res;
        }
        Deque<TreeNode> deuqe = new LinkedList<>();
        deuqe.offer(root);
        while (!deuqe.isEmpty()) {
            int size = deuqe.size();
            for (int i = 0; i < size; i++) {
                TreeNode poll = deuqe.poll();
                if (i == 0) {
                    res = poll.val;
                }
                if (poll.left != null) {
                    deuqe.offer(poll.left);
                }
                if (poll.right != null) {
                    deuqe.offer(poll.right);
                }
            }
        }
        return res;
    }
}


class Solution0513_2 {//递归法
    private int Deep = -1;
    private int value = 0;

    public int findBottomLeftValue(TreeNode root) {
        value = root.val;
        findLeftValue(root, 0);
        return value;
    }

    private void findLeftValue(TreeNode root, int deep) {
        if (root == null) return;
        if (root.left == null && root.right == null) {
            if (deep > Deep) {
                value = root.val;
                Deep = deep;
            }
        }
        if (root.left != null) findLeftValue(root.left, deep + 1);
        if (root.right != null) findLeftValue(root.right, deep + 1);
    }
}

0112_路径总和

package com.question.solve.leetcode.programmerCarl2._07_binaryTrees;

import java.util.ArrayList;
import java.util.Stack;

public class _0112_路径总和 {
}

/**
 * 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 Solution0112 {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        ArrayList<Integer> paths = new ArrayList<>();
        Boolean flag = false; //使用 Boolean包装类 来存储flag的状态
        traversal(root, paths, targetSum, flag);//flag不能是基本数据类型,
        return flag; //简化返回逻辑,直接返回flag

//        int[] flag = new int[1]; //使用长度为1的数组来存储flag的状态
//        //Integer flag = 0; //使用 Integer包装类 来存储flag的状态
//        //Boolean flag = false; //使用 Boolean包装类 来存储flag的状态
//        traversal(root, paths, targetSum, flag);
//        return flag[0] == 1; //简化返回逻辑
    }

    private void traversal(TreeNode root, ArrayList<Integer> paths, int targetSum, Boolean flag) {
        if (root == null || flag) { //如果 flag 已经为 true,则不再进行遍历
            return;
        }
        paths.add(root.val);
        if (root.left == null && root.right == null) {
            int sum = 0;
            for (int x : paths) {
                sum += x;
            }
            if (sum == targetSum) {
                flag = true;
                return;
            }
        }
        if (root.left != null) {
            traversal(root.left, paths, targetSum, flag);
            paths.remove(paths.size() - 1);
        }
        if (root.right != null) {
            traversal(root.right, paths, targetSum, flag);
            paths.remove(paths.size() - 1);
        }
    }
}

class Solution0112_2 {
    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;
        }
        if (root.left != null) {
            boolean left = haspathsum(root.left, targetsum);
            if (left) {      //已经找到
                return true;
            }
        }
        if (root.right != null) {
            boolean right = haspathsum(root.right, targetsum);
            if (right) {     //已经找到
                return true;
            }
        }
        return false;
    }

    public boolean haspathsum2(TreeNode root, int targetsum) {//lc112 简洁方法
        if (root == null) return false; //为空退出

        //叶子节点判断是否符合
        if (root.left == null && root.right == null) return root.val == targetsum;

        //求两侧分支的路径和
        return haspathsum2(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
    }
}

class Solution0112_3 {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) return false;
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<Integer> stack2 = new Stack<>();
        stack1.push(root);
        stack2.push(root.val);
        while (!stack1.isEmpty()) {
            int size = stack1.size();

            for (int i = 0; i < size; i++) {
                TreeNode node = stack1.pop();
                int sum = stack2.pop();

                //如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回true
                if (node.left == null && node.right == null && sum == targetSum) {
                    return true;
                }
                //右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
                if (node.right != null) {
                    stack1.push(node.right);
                    stack2.push(sum + node.right.val);
                }
                //左节点,压进去一个节点的时候,将该节点的路径数值也记录下来
                if (node.left != null) {
                    stack1.push(node.left);
                    stack2.push(sum + node.left.val);
                }
            }
        }
        return false;
    }

    public boolean hasPathSum2(TreeNode root, int targetSum) {
        Stack<TreeNode> treeNodeStack = new Stack<>();
        Stack<Integer> sumStack = new Stack<>();

        if (root == null)
            return false;
        treeNodeStack.add(root);
        sumStack.add(root.val);

        while (!treeNodeStack.isEmpty()) {
            TreeNode curr = treeNodeStack.peek();
            int tempsum = sumStack.pop();
            if (curr != null) {
                treeNodeStack.pop();
                treeNodeStack.add(curr);
                treeNodeStack.add(null);
                sumStack.add(tempsum);
                if (curr.right != null) {
                    treeNodeStack.add(curr.right);
                    sumStack.add(tempsum + curr.right.val);
                }
                if (curr.left != null) {
                    treeNodeStack.add(curr.left);
                    sumStack.add(tempsum + curr.left.val);
                }
            } else {
                treeNodeStack.pop();
                TreeNode temp = treeNodeStack.pop();
                if (temp.left == null && temp.right == null && tempsum == targetSum)
                    return true;
            }
        }
        return false;
    }
}

0113_路径总和ii

package com.question.solve.leetcode.programmerCarl2._07_binaryTrees;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class _0113_路径总和II {
}

/**
 * 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 Solution0113 {
    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<>();
        traversal(root, targetSum, res, paths);
        return res;
    }

    private void traversal(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> paths) {
        if (root == null) {
            return;
        }
        paths.add(root.val);
        if (root.left == null && root.right == null) {
            int sum = paths.stream().mapToInt(Integer::intValue).sum();
            if (targetSum == sum) {
                res.add(new ArrayList<>(paths));
            }
        }
        if (root.left != null) {
            traversal(root.left, targetSum, res, paths);
            paths.remove(paths.size() - 1);
        }
        if (root.right != null) {
            traversal(root.right, targetSum, res, paths);
            paths.remove(paths.size() - 1);
        }
    }
}

class Solution0113_2 {
    public List<List<Integer>> pathsum(TreeNode root, int targetsum) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null) return res;//非空判断
        List<Integer> path = new LinkedList<>();
        preOrderDfs(root, targetsum, res, path);
        return res;
    }

    public void preOrderDfs(TreeNode root, int targetsum, List<List<Integer>> res, List<Integer> path) {
        path.add(root.val);
        if (root.left == null && root.right == null) {//遇到了叶子节点
            if (targetsum - root.val == 0) {//找到了和为targetSum的路径
                res.add(new ArrayList<>(path));
            }
            return;//如果和不为targetSum,返回
        }

        if (root.left != null) {
            preOrderDfs(root.left, targetsum - root.val, res, path);
            path.remove(path.size() - 1); //回溯
        }
        if (root.right != null) {
            preOrderDfs(root.right, targetsum - root.val, res, path);
            path.remove(path.size() - 1); //回溯
        }
    }
}

class Solution0113_3 {
    List<List<Integer>> result;
    LinkedList<Integer> path;

    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        result = new LinkedList<>();
        path = new LinkedList<>();
        travesal(root, targetSum);
        return result;
    }

    private void travesal(TreeNode root, int count) {
        if (root == null) return;
        path.offer(root.val);
        count -= root.val;
        if (root.left == null && root.right == null && count == 0) {
            result.add(new LinkedList<>(path));
        }
        travesal(root.left, count);
        travesal(root.right, count);
        path.removeLast();//回溯
    }
}

class Solution0113_4 {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {//DFS统一迭代法
        List<List<Integer>> result = new ArrayList<>();
        Stack<TreeNode> nodeStack = new Stack<>();
        Stack<Integer> sumStack = new Stack<>();
        Stack<ArrayList<Integer>> pathStack = new Stack<>();
        if (root == null)
            return result;
        nodeStack.add(root);
        sumStack.add(root.val);
        pathStack.add(new ArrayList<>());

        while (!nodeStack.isEmpty()) {
            TreeNode currNode = nodeStack.peek();
            int currSum = sumStack.pop();
            ArrayList<Integer> currPath = pathStack.pop();
            if (currNode != null) {
                nodeStack.pop();
                nodeStack.add(currNode);
                nodeStack.add(null);
                sumStack.add(currSum);
                currPath.add(currNode.val);
                pathStack.add(new ArrayList(currPath));
                if (currNode.right != null) {
                    nodeStack.add(currNode.right);
                    sumStack.add(currSum + currNode.right.val);
                    pathStack.add(new ArrayList(currPath));
                }
                if (currNode.left != null) {
                    nodeStack.add(currNode.left);
                    sumStack.add(currSum + currNode.left.val);
                    pathStack.add(new ArrayList(currPath));
                }
            } else {
                nodeStack.pop();
                TreeNode temp = nodeStack.pop();
                if (temp.left == null && temp.right == null && currSum == targetSum)
                    result.add(new ArrayList(currPath));
            }
        }
        return result;
    }
}

0106_从中序与后序遍历序列构造二叉树

package com.question.solve.leetcode.programmerCarl2._07_binaryTrees;

import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

public class _0106_从中序与后序遍历序列构造二叉树 {
}

/**
 * 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 Solution0106 {
    Map<Integer, Integer> map; //方便根据数值查找位置

    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) { //用map保存中序序列的数值对应位置
            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;
        }
        int rootIndex = map.get(postorder[postEnd - 1]);  // 找到后序遍历的最后一个元素在中序遍历中的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);  // 构造结点
        int lenOfLeft = rootIndex - inBegin;  // 保存中序左子树个数,用来确定后序数列的个数
        root.left = findNode(inorder, inBegin, rootIndex,
                postorder, postBegin, postBegin + lenOfLeft);
        root.right = findNode(inorder, rootIndex + 1, inEnd,
                postorder, postBegin + lenOfLeft, postEnd - 1);

        return root;
    }
}

class Solution0106_2 {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if (postorder.length == 0 || inorder.length == 0)
            return null;
        return buildHelper(inorder, 0, inorder.length, postorder, 0, postorder.length);
    }

    private TreeNode buildHelper(int[] inorder, int inorderStart, int inorderEnd, int[] postorder, int postorderStart, int postorderEnd) {
        if (postorderStart == postorderEnd)
            return null;
        int rootVal = postorder[postorderEnd - 1];
        TreeNode root = new TreeNode(rootVal);
        int middleIndex;
        for (middleIndex = inorderStart; middleIndex < inorderEnd; middleIndex++) {
            if (inorder[middleIndex] == rootVal)
                break;
        }

        int leftInorderStart = inorderStart;
        int leftInorderEnd = middleIndex;
        int rightInorderStart = middleIndex + 1;
        int rightInorderEnd = inorderEnd;

        int leftPostorderStart = postorderStart;
        int leftPostorderEnd = postorderStart + (middleIndex - inorderStart);
        int rightPostorderStart = leftPostorderEnd;
        int rightPostorderEnd = postorderEnd - 1;
        root.left = buildHelper(inorder, leftInorderStart, leftInorderEnd, postorder, leftPostorderStart, leftPostorderEnd);
        root.right = buildHelper(inorder, rightInorderStart, rightInorderEnd, postorder, rightPostorderStart, rightPostorderEnd);
        return root;
    }
}

class Solution0106_3 {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        if (postorder == null || postorder.length == 0) {
            return null;
        }
        TreeNode root = new TreeNode(postorder[postorder.length - 1]);
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        stack.push(root);
        int inorderIndex = inorder.length - 1;
        for (int i = postorder.length - 2; i >= 0; i--) {
            int postorderVal = postorder[i];
            TreeNode node = stack.peek();
            if (node.val != inorder[inorderIndex]) {
                node.right = new TreeNode(postorderVal);
                stack.push(node.right);
            } else {
                while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) {
                    node = stack.pop();
                    inorderIndex--;
                }
                node.left = new TreeNode(postorderVal);
                stack.push(node.left);
            }
        }
        return root;
    }
}

0105_从前序与中序遍历序列构造二叉树

package com.question.solve.leetcode.programmerCarl2._07_binaryTrees;

import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

public class _0105_从前序与中序遍历序列构造二叉树 {
}

/**
 * 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 Solution0105 {
    Map<Integer, Integer> map;

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) {//用map保存中序序列的数值对应位置
            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 (preBegin >= preEnd || inBegin >= inEnd) {//不满足左闭右开,说明没有元素,返回空树
            return null;
        }
        int rootIndex = map.get(preorder[preBegin]);  //找到前序遍历的第一个元素在中序遍历中的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);  //构造结点
        int lenOfLeft = rootIndex - inBegin;  //保存中序左子树个数,用来确定前序数列的个数
        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;
    }
}

class Solution0105_2 {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || preorder.length == 0) {
            return null;
        }
        TreeNode root = new TreeNode(preorder[0]);
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        stack.push(root);
        int inorderIndex = 0;
        for (int i = 1; i < preorder.length; i++) {
            int preorderVal = preorder[i];
            TreeNode node = stack.peek();
            if (node.val != inorder[inorderIndex]) {
                node.left = new TreeNode(preorderVal);
                stack.push(node.left);
            } else {
                while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) {
                    node = stack.pop();
                    inorderIndex++;
                }
                node.right = new TreeNode(preorderVal);
                stack.push(node.right);
            }
        }
        return root;
    }
}