ORID25

作者: Wilbur_ | 来源:发表于2020-06-06 21:01 被阅读0次

睡眠质量真的影响自己第二天的心情……我觉得做完就睡的很好,然后早上起来神清气爽,做事情也很高兴。就是不会觉得自己脑子混混僵僵的,所以保证自己有一个好的睡眠质量真的很重要,能让自己第二天有个好心情做事。

[235&236] Lowest common ancestor of a binary search tree解题报告

算法

用divide and conquer 算法
为什么用这个算法(那些条件)?
因为这是一个二叉树,所以可以用divide and conquer来实现
为了找到他们的“祖先”,或者说上一级,你就需要能够不断的从这个节点往下面走,直到走到p或者q的位置,然后返回他们的祖先。

代码实现

有什么要注意的地方
判断条件要想清楚,因为你在递归的时候要判断返回什么?以及什么条件才能返回它?

if (root == null || root == p || root == q) {
    return root;
}

这里为什么要return root呢?因为一旦root等于null,那么就是你递归到二叉树的最底部了,并且在过程中你没有找到p 或者 q, 所以返回root,如果找到了,那么返回root(如果直接看这一行可能会有点蒙,但看到后面你就知道为什么要返回root了),因为你在递归进入到下一层的时候,你pass的参数是:
root.left(or root.right), p , q
所以实际上这时候如果你找到了p,q的祖先,返回的将是当前root
以下是整段代码

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || root == p || root == q) {
            return root;
        }
        //这上面是返回条件(递归的出口),也就是递归时候的返回条件
        //这下面是divide部分,分成左和右
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        //conquer部分,一开始看起来有点蒙,但是你看一下出口的条件就明白了,left != null 就意味着左边找到了其中一个祖先, right != null也一样,      
        //只有当他俩同时不是null的时候才说明找到了共同祖先。否则只是找到了其中一个(其实如果这个二叉树必须有个root,以及给你的两个node都 
        //存在在这棵树上面,那后面的判断已经没必要了。因为这一行就确保你找到p和q,最差最差也会return root(也就是根部)

        if (left != null && right != null) {
            return root;
        }
        if (left != null) {
            return left;
        }
        if (right != null) {
            return right;
        }
        return null;

    }

有什么可以优化的地方

时空复杂度分析

O(n) 因为最坏情况你就要把每一个node都走一遍。

相关题目有哪些做过的

跟哪个题目比较像?
目前没想到……

[124] Binary tree maximum path sum解题报告

算法

用什么算法
Divide and conquer
为什么用这个算法(那些条件)?
因为要用递归来寻找到最大的路径

代码实现

有什么要注意的地方
这题要注意的地方实在是太多了……我一开始的方法没错(D&C),结果好多edge case弄得我焦头烂额,不断加if else的判断,但是最后始终有问题,比如只给你[-3], or [-2, -1],or [1, -2, 3] 我一开始只是把左右拆开,return最大值(由于出口设置的值为0,所以最后到null之后一定返回0,但是如果整棵树上都是负数,那返回的值就不对了。)
然后我就改了一下,可以返回负数,但是发现负数也有个问题,就是如果root为负数,你要考虑他的孩子是否比他大,如果root不为负数,你要考虑左右两边是否曾经有过负数。比如这个例子[1,-2,-3,1,3,-2,null,-1]
返回的值就应该是3,因为3是在-2下面的,如果你最后返回4就错了……我当时还在想是否要用boolean flag去验证路径上是否有负数,结果还是有问题。

最后看了别人的答案,发现最好的方式还是要用一个global variable,然后keep track of max value. 而且必须用root.val + left + right compare to max 这样你就直接知道了当前节点和他的孩子的和是否比max大,如果大就保存起来,如果不是就不保存。
这是那个人的代码

public class Solution {
    int max = Integer.MIN_VALUE;
    
    public int maxPathSum(TreeNode root) {
        helper(root);
        return max;
    }
    
    // helper returns the max branch 
    // plus current node's value
    int helper(TreeNode root) {
        if (root == null) return 0;
        
        int left = Math.max(helper(root.left), 0);
        int right = Math.max(helper(root.right), 0);
        
        max = Math.max(max, root.val + left + right); //这个就是在记录最大值, 而且不会受到全是负数的影响,因为如果底下两层是负数,他在上两句的      
                                                     //时候已经把他们变为0了,而之前也记录了他们的最大值(上一次递归的时候会记录负数的最大值,
                                                    //因为MIN_VALUE 比任何负数都要小,这时候相加只得到root.val并且把它和之前的最大值比较。
        
        return root.val + Math.max(left, right);  //这其实保证了负数会被返回上一层
    }
}

有什么可以优化的地方

时空复杂度分析

...

相关题目有哪些做过的

跟哪个题目比较像?
都是divide and conquer

相关文章

  • ORID25

    每天记录自己干了什么这点时间绝对不能省…… 因为这是你在之后回顾自己这段时间究竟干了什么的重要根据,而且是你总结自...

  • ORID25

    睡眠质量真的影响自己第二天的心情……我觉得做完就睡的很好,然后早上起来神清气爽,做事情也很高兴。就是不会觉得自己脑...

网友评论

      本文标题:ORID25

      本文链接:https://www.haomeiwen.com/subject/nbrwzhtx.html