代码随想录第十八天

代码随想录第十八天

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

Leetcode 513. 找树左下角的值

题目链接: 找树左下角的值
自己的思路:层序遍历(超级简单)!!

正确思路:层序遍历、递归
层序遍历代码:

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        LinkedList<TreeNode> queue = new LinkedList<>();
        //存最后的结果
        int res = 0;
        if (root!=null) queue.add(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            //如果为每一层的第一个,则给res赋值
            res = queue.peek().val;
            while(size--!=0){
                TreeNode node = queue.poll();
                if (node.left!=null) queue.add(node.left);
                if (node.right!=null) queue.add(node.right);                    
            }
        }
        return res;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

递归代码:递归的代码理解为前中后序都可以,因为实际没有中序的逻辑;递归三部曲:1、传入参数:当前结点及当前节点的深度;2、终止条件:当当前节点为空的时候终止;3、单层逻辑:当当前深度大于最大深度的时候,更新最大深度和res的值,然后进行左右递归,注意,这里必须先进行左递归,因为最后的res的值可能出现在左节点上,也可能出现在右节点上,这样的目的是保证如果最后一层左节点在最左边,那么结果一定是它的值!!!

class Solution {
    int res,maxdepth;
    public int findBottomLeftValue(TreeNode root) {
        dfs(root,1);
        return res;
    }

    public void dfs(TreeNode node,int depth){
        if (node==null) return;
        //如果当前深度大于最大深度,改变res的值
        if (depth>maxdepth){
            maxdepth = depth;
            res = node.val;
        }
        //这里必须先进行左递归!!!
        //这里的传入参数是depth+1,起始隐藏这回溯的逻辑
        dfs(node.left,depth+1);
        dfs(node.right,depth+1);
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)

Leetcode 112. 路径总和

题目链接: 路径总和
自己的思路:不会!!!自己写的只能过百分之五十的例子!!!主要是终止条件没有设置好!!!

正确思路:递归三部曲:1、传入参数:当前节点和当前剩余的和(减完);2、终止条件:当当前结点为空的时候,返回false,如果当前结点是叶子结点,而且当前结点的值和剩余的和的值相等,返回true,否则返回false;3、单层递归:分别向左和向右递归,并且用或运算连接!!!!

代码:

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        //终止条件
        if (root==null) return false;
        if (root.left==null&&root.right==null){
            //正好把sum减为0
            return root.val==targetSum;
        }
        //单层递归逻辑
        return hasPathSum(root.left,targetSum-root.val)||hasPathSum(root.right,targetSum-root.val);
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)

Leetcode 113. 路径总和 II

题目链接: 路径总和 II
自己的思路:res.add()那里使用的res.add(path),一直得不到想要的结果

正确思路:递归三部曲:1、传入参数:当前节点,剩余的和;2、终止条件:碰到空节点或者叶子节点,如果碰到叶子节点,并且满足路径之和等于sum,将路径加入到res中(因为是值传递,所以要new一个新的对象),然后回溯,返回,否则直接回溯返回;3、单层逻辑:左右进行递归,然后回溯当前节点!!!!

代码:

class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        dfs(root,targetSum);
        return res;
    }

    public void dfs(TreeNode node,int target){
        if (node==null) return;
        path.add(node.val);
        //当碰到叶子节点时
        if (node.left==null&&node.right==null){
        	//将符合条件的路径加入到res中
            if (target==node.val) res.add(new ArrayList(path));
            //回溯
            path.remove(path.size()-1);
            return;
        }
        dfs(node.left,target-node.val);
        dfs(node.right,target-node.val);
        //回溯
        path.remove(path.size()-1);
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

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

题目链接: 从中序与后序遍历序列构造二叉树
自己的思路:想到如何去构建,但是不会写代码!!!!

正确思路:给定了中序遍历左中右和后序遍历左右中,如果想构造出二叉树来,那么一定要找到后序遍历的最后一个节点,通过这个节点来拆分中序遍历的左右子树,然后拆分出中序遍历的左右子树,通过左右子树的长度进而确定后序遍历中的左右子树即可!!递归三部曲:1、传入参数:前序遍历左(右)子树的起始点和终止点,后序遍历左(右)子树的起始点和终止点;2、终止条件:当数组不成立时即返回;3、单层逻辑:先找后序遍历的最后一个节点,通过这个节点找中序遍历的根结点,然后左右递归即可!!

代码:

class Solution {
    //构造一个map用于存放中序遍历中各个结点值和其索引
    Map<Integer,Integer> map = new HashMap<>();
    //后序遍历
    int[] post;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        for (int i =0;i<inorder.length;i++) map.put(inorder[i],i);
        post = postorder;
        TreeNode root = buildTree(0,inorder.length-1,0,postorder.length-1);
        return root;
    }

    public TreeNode buildTree(int il,int ir,int pl,int pr){
        if (ir<il||pr<pl) return null;
        //找到后序遍历中最后一个节点的值
        int pnode = post[pr];
        //去中序中寻找索引
        int inode = map.get(pnode);
        TreeNode node = new TreeNode(pnode);
        //递归左右子树
        node.left = buildTree(il,inode-1,pl,pl+inode-1-il);
        node.right = buildTree(inode+1,ir,pl+inode-il,pr-1);
        return node;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

Leetcode 105. 从前序与中序遍历序列构造二叉树

题目链接: 从前序与中序遍历序列构造二叉树
自己的思路:会上一个就会这一个,基本一模一样!!!!!

正确思路:

代码:

class Solution {
    Map<Integer,Integer> map = new HashMap<>();
    int[] pre;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        for (int i =0;i<inorder.length;i++) map.put(inorder[i],i);
        pre = preorder;
        TreeNode root = buildTree(0,inorder.length-1,0,preorder.length-1);
        return root;
    }

    public TreeNode buildTree(int il,int ir,int pl,int pr){
        if (ir<il||pr<pl) return null;
        int pnode = pre[pl];
        int inode = map.get(pnode);
        TreeNode root = new TreeNode(pnode);
        root.left = buildTree(il,inode-1,pl+1,pl+inode-il);
        root.right = buildTree(inode+1,ir,pl+inode-il+1,pr);
        return root;
    }
}

复杂度分析
时间复杂度: O ( n ) \mathcal{O}(n) O(n)
空间复杂度: O ( n ) \mathcal{O}(n) O(n)

你可能感兴趣的:(深度优先,算法)