LeetCode 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.

就是说,x轴上在1,2,…,n点上有许多垂直的线段,长度依次是a1, a2, …, an。找出两条线段,使他们和x抽围成的面积最大。面积公式是 Min(ai, aj) X |j - i|

解法1:大家都能想到的,穷举所有(i,j)可能,找一个最大的。

这里有一点比较重要,第一层遍历是以i 为右边界,这样我们每轮遍历的最大length就定了,就可以有优化的空间,否则如果以i为左边界,那么往右遍历,length也添加,value又是不定值,就多了个变量

//O(n^2)
     public static int maxArea(int[] height) {
         // Start typing your Java solution below
         // DO NOT write main() function
         int maxArea = 0;
         for(int i = 1; i < height.length; i++){
             if(height[i] == 0)continue;
             for(int j = 0; j < i; j++) {
                 int area = area(height,i,j);
                 if(area > maxArea) {
                     maxArea = area;
                 }
             }
         }
         return maxArea;
     }

O(n^2)穷举
//不过这样的话无法通过leetcode大集合。

解法2:可以对解法1中的第二个循环中的j做预先判断从而跳过某些情况,做一点优化。在我们检查比i小的各个j时,计算面积的短板不会超过ai本身。平均到距离上,如果距离小于这个平均距离那就可以跳过了。

public static int maxArea(int[] height) {
         // Start typing your Java solution below
         // DO NOT write main() function
         int maxArea = 0;
         for(int i = 1; i < height.length; i++){
             if(height[i] == 0)continue;
             int maxPossibleIdx = i - maxArea/height[i];
             for(int j = 0; j < i && j <= maxPossibleIdx; j++) {
                 int area = area(height,i,j);
                 if(area > maxArea) {
                     maxArea = area;
                 }
             }
         }
         return maxArea;
     }

O(n^2)预判断

解法3: O(n)的复杂度。保持两个指针i,j;分别指向长度数组的首尾。如果ai 小于aj,则移动i向后(i++)。反之,移动j向前(j–)。如果当前的area大于了所记录的area,替换之。
这个想法的基础是,如果i的长度小于j,无论如何移动j,短板在i,不可能找到比当前记录的area更大的值了,只能通过移动i来找到新的可能的更大面积。

这里也是因为我们是从头尾开始遍历,使得length本身是最大的。少了一个变量,这很重要!!!

public static int maxArea(int[] height){
        int maxArea = 0;
        int i = 0;
        int j = height.length - 1;
        if(j <=0)return 0;
        while(i < j) {
            int area = area(height, i, j);
            if(height[i] < height[j]){
                i++;

            }else {
                j--;
            }
            if(area > maxArea) maxArea = area;
        }
        return maxArea;
    }

O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值