算法--------数组--------容纳最多的水

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和
 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。


在这里插入图片描述
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49

我的解答:

class Solution {
    public int maxArea(int[] height) {
           int length = height.length;
        if (length == 0) {
            return 0;
        }else if (length == 1){
            return height[0];
        }

        int max = 0;
        for (int i =0, j =length -1; j > i ;  ){
            int minHeight = Math.min(height[i], height[j]);
            max = Math.max(max,minHeight * (j -i));
            if (height[i] > height[j]) {
                j--;
            }else {
                i++;
            }
        }
        return max;
    }
}

看到网上优化过的之后:

class Solution {
    public int maxArea(int[] height) {
        int length = height.length;
        if (length == 0) {
            return 0;
        }else if (length == 1){
            return height[0];
        }

        int max = 0;
        for (int i =0, j =length -1; j > i ;  ){
            int start = height[i];
            int end = height[j];
            int minHeight = Math.min(start, end);
            max = Math.max(max,minHeight * (j -i));
//            if (start > end) {
//                while (height[--j]<end && j> i);
//            }else {
//                while (height[++i]<end && j> i);
//            }

                        if (start > end) {
                do {
                    j--;
                }while (height[j]<end && j> i);
            }else {
                do {
                    i++;
                }while (height[i]<start && j> i);
            }
        }
        return max;
    }
}

下面分析下解题思路:

双索引,左右开弓。第一次遍历的肯定是左右两边的两个数。这时候,比较两个数,放弃比较小的那个数,继续遍历。为什么可以放过最小的那个数呢?
比如说左边的数,比右边的数小,那么对于左边那个数来说,他存在最大的值,就是最右边那个。因为对于左边那个数来说,和其他任何位置的组合,都没有最右边那个数大,所以,对于左边那个小的数,可以不用再遍历。一定是最大的组合。那么,这个数就可以不用遍历了。以此类推。时间复杂度是O(n);

依次类推可以得到每一个数和其他数组合的最大值。然后得出最大值就可以了。

总结:

1.看到别人的算法,总是可以让自己学到点什么。
2.解题思路很重要。思考问题的方式很重要。

解决过程:

刚开始,我做题的时候,同事在旁边,给我说了思路,左右遍历,然后小的数扔掉。当时,我担心的是,这样的话,会不会错失掉最大值?因为有些情况没有遍历,后来,我去尝试推翻同事的解法,后来发现,他是对的。思路就是上面我写的。嗯,我觉得,对任何人说的,都应该质疑,推翻,这会让你印象更深刻。这才有学习的意义。才有意思。

posted @ 2019-01-18 11:26  有点理想的码农  阅读(505)  评论(0编辑  收藏  举报