leetcode 11 Container With Most Water

Container With Most Water
Total Accepted: 48739 Total Submissions: 153072

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.

这道题意思很明确,就是给出一些点,然后将这些点与x轴做垂线,这样就形成许多条垂线段,把这些垂线段想象成木桶的桶壁,x轴想象成木桶的桶底,题目要求在其中选出两个桶壁,使得形成的木桶装水的体积最大。

这道题最直观的想法就是搜索所有可能的桶壁的组合,找出使得装水体积最大的组合。但这样一来,就是 O(n2) 的。提交测试果然超时,挂在一组有15000个点的测试用例上。后来尝试添加一些判断条件,减少搜索次数,但是效果甚微。后来看小Discuss,原帖地址:https://leetcode.com/discuss/53305/a-fast-and-easy-understand-cpp-solution 发现原来有一种 O(n) 的方法。只用扫一遍,就可以找出最大体积。

该方法的主要过程是这样的,一头一尾用两个指针,计算两者形成的木桶的装水体积。然后选两者较小的一个,把它往靠近中间位置移一格,如果,新的桶壁高度不如之前移动的桶壁,那么就再往中间位置移一格,重复这个过程,直到新的桶壁高度高于移动的桶壁。然后再计算新形成的木桶的装水的体积。然后再选择两者较小的一个,把它往靠近中间位置移一格,重复上面的过程,直到两个指针重合。此时的最大体积,就是我们要求的所有可能组合中的最大体积。

我们用一个例子来说明这个过程:
这里写图片描述
总共6块桶壁,那么我们首先计算首尾两个桶壁形成的木桶的装水体积
这里写图片描述
然后我们比较两个桶壁的大小,找出小的一个,然后向中间移动一格。此时我们要移动的就是指向6号桶壁的指针,让它指向5号桶壁,这样一次移动其实就排除了2-6,3-6, 4-6,5-6四种组合,因为这四种组合不可能体积大于1-6. 原因很简单,首先底边长度小于1-6组合,其次由于都和6号桶壁组合所以高度最多为4(即6号桶壁的高度)而1-6组合的高度就是4,所以乘起来的结果必然小于1-6组合,所以直接淘汰掉。下面比较新指向的5号桶壁和6号桶壁的高度,如果5号桶壁的高度低于等于6号桶壁的高度那么5号桶壁淘汰,因为所有与5号桶壁的组合都有一个对应的与6号桶壁的组合,并且底边比其长1。例如:1-5对应1-6, 2-5对应2-6, 3-5对应3-6… …但在高度上1-5组合为min(h1,h5),1-6组合为min(h1,h6),而h5 h6, 所以min(h1,h5) min(h1,h6),因此,对应的6号桶壁的组合装水体积更大,对于2-5,3-5等也是同样的道理,都会小于等于2-6,3-6等。因此5号桶壁的组合不会产生比6号桶壁的组合产生更多的装水体积。所以5号桶壁被淘汰。但在我们的例子中,5号桶壁的高度高于6号桶壁的高度,所以就有可能产生更多的装水体积,所以不能直接淘汰,需要计算体积。之前最大的1-6组合体积为20,现在1-5组合的体积也为20. 所以最大体积不变,接着我们重复上面的过程,在找出1号桶壁和5号桶壁中高度较小的一个,然后将它向中间移一格,于是指向1号桶壁的指针指向了2号桶壁,这个过程排除了1-2,1-3,1-4这三种组合,6号桶壁因为之前已经被淘汰了,所以1-6之前就被排除了,排除1-2,1-3,1-4的理由和之前排除2-6,3-6, 4-6,5-6是一样的道理,不再赘述。现在1号桶壁和6号桶壁都被淘汰了,现在比较2号桶壁与之前的桶壁(1号桶壁)的高度,发现2号桶壁比1号桶壁高度更低,那么2号桶壁直接就淘汰了,原因我之前比较5号和6号桶壁时就介绍了。现在1,2,6号桶壁都被淘汰了。那么我们把指向2号桶壁的指针继续向中间移指向3号桶,比较3号桶和之前的桶壁(1号桶壁)的高度,发现3号桶壁更高,所以重新计算体积,体积为12,因此最大体积仍为20。值得注意的一点是之前的桶壁不是2号桶壁,而是之前进行计算的1号桶壁,因为当我们重新计算体积时,才会更新桶壁,2号桶壁直接被淘汰了,所以没有进行计算,因此不算作之前的桶壁。

接下来比较3号桶壁和5号桶壁的高度,发现5号桶壁较矮,所以指向5号桶壁的指针改指向4号桶壁,5号桶壁被淘汰,对应的4-5组合被排除,比较4号桶壁和之前的桶壁(即5号桶壁),4号桶壁比较高,所以重新计算体积,体积为7. 因此最大体积仍为20,然后比较3号桶壁和4号桶壁,发现3号桶壁较矮,因此移动指向3号桶壁的指针指向4号桶壁,3号桶壁被淘汰(注意:我所说的淘汰是指它没有机会产生比当前最大值更大的体积)。此时首尾两个指针都指向4号桶壁,指针重合,因此退出循环。当前的最大体积就是所有可能组合的最大体积。

下面是程序的完整代码:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;


int maxArea(int* height, int heightSize) 
{
    if(heightSize < 2)
        return 0;

    int indexl = 0, indexr = heightSize - 1;
    int max = 0, tmpArea = 0;
    int currentHeight = 0;

    while(indexl < indexr)
    {
        if(height[indexl] < height[indexr])
        {
            tmpArea = height[indexl] * (indexr - indexl);
            max = max < tmpArea ? tmpArea : max;
            currentHeight = height[indexl];
            indexl++;
            while(indexl < indexr && height[indexl] <= currentHeight)
            {
                indexl++;
            }
        }
        else
        {
            tmpArea = height[indexr] * (indexr - indexl);
            max = max < tmpArea ? tmpArea : max;
            currentHeight = height[indexr];
            indexr--;
            while(indexl < indexr && height[indexr] <= currentHeight)
            {
                indexr--;
            }
        }
    }
    return max;
}

int main()
{
    int heightSize;
    cout<<"Input the heightSize:"<<endl;
    cin>>heightSize;

    int *height = (int*)malloc(sizeof(int) * heightSize);
    for(int i = 0; i < heightSize; i++)
        scanf("%d,", &height[i]);
    cout<<maxArea(height, heightSize)<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目"leetcode 11"是一个关于容器装水的问题。给定一个非负整数数组height,数组的每个元素表示当前位置的高度。我们需要在数组中选择两个位置,在这两个位置之间形成的容器可以容纳最多的水。要求返回容器的最大容量。 根据引用中的代码,我们可以使用双指针的方法来解决这个问题。首先,我们初始化两个指针,一个指向数组的头部,一个指向数组的尾部。然后,我们计算当前两个指针所形成的容器的容量,即两个指针之间的距离乘以两个指针所对应的高度中较小的一个。我们将计算得到的容量与之前的最大容量进行比较,更新最大容量的值。接下来,我们移动指针的规则是,如果左指针所对应的高度小于右指针所对应的高度,则将左指针向右移动一位;之,如果右指针所对应的高度小于左指针所对应的高度,则将右指针向左移动一位。我们重复这个过程,直到左指针和右指针相遇为止。 通过这种方法,我们可以找到最大的容器装水量,并将其作为结果返回。根据引用和引用中的代码示例,我们可以实现以下的算法来解决这个问题: ```java public static int maxArea(int[] height) { int left = 0; int right = height.length - 1; int maxArea = 0; while (left < right) { int currentArea = Math.min(height[left], height[right]) * (right - left); maxArea = Math.max(maxArea, currentArea); if (height[left < height[right]) { left++; } else { right--; } } return maxArea; } ``` 这个算法的时间复杂度是O(N),其中N是给定数组的长度。算法使用了双指针的方法,每次移动指针都可以排除一些不可能形成最大容器的情况,从而减少了不必要的计算。这使得算法具有较高的效率。 综上所述,根据给定的引用内容,我们可以使用双指针的方法来解决"leetcode 11"这个问题,找到数组中能够容纳最多水的容器的容量。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [leetcode11-leetCode:leetcode](https://download.csdn.net/download/weixin_38665490/19947831)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [LeetCode第十一题: 盛最多水的容器 (Java)](https://blog.csdn.net/a1111116/article/details/124206005)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值