过去会遗忘,现在不会

盛水最多的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

 

 

乍一看几乎没啥思路,不过把题目抽象一下,不就是求一个长方形的面积吗?而且这个长方体的长和高都是动态的,且高是左右两边最小的那一个。

那么最粗暴的解法就有了,从nums[0]开始算,求nums[0]~nums[i]组成的面积,长是i-0,高是min{nums[0],nums[i]},i表示数组下标

之后从num[1],nums[2].......计算,最后找到最大的那个就行

不过这样对于算法肯定是不行的,因为要算的面积太多了。

 

所以思考一下怎么减少计算量??长度每次都会递增1,高度不确定?

想一下,找个数组里面最小的数,那么它组成的所有长方形的高肯定就是它本身,因此找离它最远的那个数组成长方形,这就是它的最大容量。

 之后找第二小的数(此时就不用考虑比和它小的数组成的长方形的面积了),找第二小的数的最大面积长方形,

之后找第三找第四.......找到最大数后停止,计算量好像减少了很多。

这么看来就很清晰了,只要对数组内的每个数找比它高且离它最远的那个就好了,之后选里面最大的那个。

class Solution {
public:
    int maxArea(vector<int>& height) {
int max=0;

for(int i=0;i<height.size();i++)
{
  int length=0;

    for(int j=0;j<height.size();j++)
    {
        if(j!=i)
        {
            if(height[j]>height[i]||height[j]==height[i])
            {
                int length_temp=abs(j-i);
                length=length>length_temp?length:length_temp;
            }
        }
    }
    int max_temp=length*height[i];
    max=max>max_temp?max:max_temp;
}

return max;
    }
};

超时!!果然O(N2)根本不行。 不过优化一下试试:

class Solution {
public:
    int maxArea(vector<int>& height) {
int max=0;

for(int i=0;i<height.size();i++)
{
  int length=0;
  if(i<height.size()/2)
  {
    for(int j=height.size()-1;j>0;j--)
    {
        if(height[j]>height[i]||height[j]==height[i])
        {
            length=abs(j-i);break;
        }
    }
  }
  else
  {
      for(int j=0;j<height.size();j++)
    {
        if(height[j]>height[i]||height[j]==height[i])
        {
            length=abs(j-i);break;
        }
    }
  }
max=max>length*height[i]?max:length*height[i];
}

return max;
    }
};

勉强能跑,因为优化了寻找最长边的循环条件,前一半的数从末尾找,后一半的数从前面找;

 但明显这样的解法不好。而且题目是关于双指针的,怎么用双指针达成O(N)的复杂度呢??

 

上面我是找每个高对应的最长边求最大面积,要找两次,先找高,再找边。反过来,我直接从最长的边开始找,直接就确定了高不是吗?这不就只用遍历一次吗?

思考一下,最长的边肯定是首尾这两个数组成的,用begin和end标记下。begin=0;end=n;(n表示数组的长度-1,end-begin就是边长) ;

 它的高度是这俩小标对应的最小的那个数,所以面积也确定了,之后缩小边(因为边只能1单位1单位的减少)再找高。

问题是,从左侧还是右侧的地方往里缩小呢??

根据题目,是要找最大的面积,我期望缩小后的这个面积是比原来大的,假如我从高处缩小,肯定不行,期望面积在减小,不行,所以只能从低处往里缩小,这样期望面积才有可能变大。

如此一来,题解就有了。

代码如下:

class Solution {
public:
    int maxArea(vector<int>& height) {
int begin=0;
int end=height.size()-1;
int max=0;
int l=0;
int h=0;
while(begin<end)
{
    l=end-begin;
if(height[begin]<height[end]||height[begin]==height[end])
{
    h=height[begin];
}
else
{
    h=height[end];
}
max=max>l*h?max:l*h;

if(h==height[begin])
{
begin++;
}
else end--;

}
return max;
    }
};

 

posted on 2023-06-18 23:38  WhatAnyWay  阅读(32)  评论(0)    收藏  举报