力扣11.盛水最多的容器

盛水最多的容器题目

思路

最开始想到的是暴力求解法,即以每一个元素为一边,计算它与另外n-1个元素分别组成的面积,取其最大值。
以第一个元素为一边,遍历n个-1元素。然后以第二个元素为一边,遍历n-2个元素。以此类推,是以等差递减的次数遍历(1 + n) * n / 2次,时间复杂度是 O ( n 2 ) O(n^2) O(n2)
这个答案会超时,因此得想想更快的方法。


假设两个边的下标分别是left和right,他们围成的面积就应该是它们之间的距离乘二者中更短的那个,即:
( r i g h t − l e f t ) ∗ m i n ( h e i g h t [ l e f t ] , h e i g h t [ r i g h t ] ) (right - left) * min(height[left], height[right]) (rightleft)min(height[left],height[right])
方便起见将其记为 a r e a = d ( 距离 ) ∗ m i n ( 最小值 ) area = d(距离) * min(最小值) area=d(距离)min(最小值)

要得到最大的面积,那么这两个因数就要越大越好。对于后者我们不方便找到两个元素作为基点去遍历数组,但对于前者,要取最大值很容易:数组的左右两端。

首先以数组首位下标为left,末位下标为right为起点,得到一个初始面积。此时如果想要继续增大面积,就得做其他尝试,即移动left或right。但无论移动哪一个,距离d都会缩小。如果移动的是二者中较长的那一个,min不会增大甚至还可能缩小,因此必须移动二者中较短的那个下标来增大min。

每次移动后如果新的面积大于旧的面积,就代表之前的端点可以被抛弃了,可以看做是找到了新的基点去遍历数组。最终左右相遇时得到的最大面积就是最终答案。由于每个元素只访问了一次,所以时间复杂度是 O ( n ) O(n) O(n)

代码

// 双指针法
class Solution {
public:
    int maxArea(vector<int>& height) {
        // 左右两端
        int left = 0, right = height.size() - 1;
        int temp, max = 0;
        while (left < right) {
            temp = (right - left) * min(height[left], height[right]);
            if (temp > max)
                max = temp;
            // 移动较短的那条边
            if (height[left] < height[right]) {
                left++;
            }
            else {
                right--;
            }
        }
        return max;
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值