zoukankan      html  css  js  c++  java
  • LeetCode: Container With Most Water

    PS:金融民工搬砖也辛苦,最近项目缓一点,终于又可以撸一撸题,预防下阿尔茨海默症

    Container With Most Water

    Given n non-negative integers a1, a2, …, an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

    Note: You may not slant the container and n is at least 2.

    拿到题,首先想到暴力破解法

    先上递归

    public int maxArea(int[] height) {
        if (height == null || height.length < 2) {
            return 0;
        }
    
        int len = height.length;
    
        if (len == 2) {
            return min(height[0], height[1]);
        }
    
        // 计算f(n-1)的结果
        int[] height_1 = new int[len - 1];
        System.arraycopy(height, 0, height_1, 0, len - 1);
        int maxArea = maxArea(height_1);
    
        for (int i = 0; i < len - 1; i++) {
            int area = (len - 1 - i) * min(height[i], height[len - 1]);
            if (maxArea < area) {
                maxArea = area;
            }
        }
        return maxArea;
    }
    public int min(int x, int y) {
        return x < y ? x : y;
    }

    提交后显示超时,接着不死心又上了个循环

    public static int maxArea2(int[] height) {
        if (height == null || height.length < 2) {
            return 0;
        }
    
        int maxArea = 0;
        int count = height.length - 1;
        for (int i = 0; i < count; i++) {
            for (int j = i + 1; j < height.length; j++) {
                int curArea = (j - i) * min(height[j], height[i]);
                maxArea = maxArea > curArea ? maxArea : curArea;
            }
        }
        return maxArea;
    }
    public int min(int x, int y) {
        return x < y ? x : y;
    }

    纳尼?还是不行。仔细想想,把所有可能性算一遍,时间复杂度都是O(n2),这题的接受条件可能是O(n)的时间复杂度。

    惭愧,想了半个小时,虽然想要抛弃一些比较,但是囿于单指针,没有想到该怎么做。so,转到discuss区,大神提供了一种O(n)的解法,双指针从两边同时扫描(初看让人有点眩晕,不过逻辑相当清晰)

    public int maxArea(int[] height) {
        if (height == null || height.length < 2) {
            return 0;
        }
    
        int left = 0, right = height.length - 1, maxArea = 0;
        while (left < right) {
            int area = (right - left) * Math.min(height[left], height[right]);
            maxArea = maxArea > area ? maxArea : area;
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        return maxArea;
    }

    这位的解释非常好,大意是:

    • 现在我们有两个指针,分别位于两头,Xleft=0,Xright=n-1。
    • 现在假设 height[Xleft] < height[Xright],如果画一个平面坐标系,就会发现,当左边线条不变,右边取任何线条,都不会比当前情况下所得到的容器的容量大,即是说:不需要计算 Xleft=0,Xright=1,2,…,n-2 这些情况。这个时候就可以放心地将 Xleft 往右移了。
    • 同理,height[Xleft] > height[Xright],向左移动 Xright
  • 相关阅读:
    Jenkins操作手册 巨详细,一篇足矣!
    获取外网的IP的方法!
    Winson.Framework 2.0 搭建FLASH视频教程!
    JS读写COOKIE的方法!
    Winson.Framework 2.0发布!
    第一次自己做的电子杂志--《深博网志》!
    ProMesh.Net基本使用说明!
    ExtJS学习心得(三)
    安装SQL2000时,最后报安装配置服务失败的解决!
    ExtJS学习心得(二)
  • 原文地址:https://www.cnblogs.com/read-the-spring-and-autumn-annals-in-night/p/12041926.html
Copyright © 2011-2022 走看看