leetcode 计算最大盛水量

来源:互联网 发布:编程开发是什么 编辑:程序博客网 时间:2024/05/01 02:45
题目出处
https://leetcode.com/problems/container-with-most-water/

给字n个非负整数, a1,a2, … , an,  对应着坐标轴(i, ai),  对每个数连接x轴画一条线段,端点 (i, ai)  和 (i, 0).
对两个数,连接端点, 再与x轴形成长方形, 求长方形的面积就想关于盛水的体积, 求最大的盛水量。

如假设给定的10个数:  [5, 4, 3, 10, 2, 7, 8, 6, 1, 9],即10 个点 (0, 5), (1, 4), (2, 3), (3, 10), … ,(9, 9)  对应的直观图如下




蓝色区域代码的是 (0, 5),(3, 10)两点的盛水量为: 5*3 = 15.
相应的, 灰色区域代码的是 (3 10),(5, 7)两点的盛水量为: 7*(5 -3) = 14.
相应的, 黄色区域代码的是 (6, 8),(9, 9)两点的盛水量为: 8*(9 -6) = 24.
上图数据中,最大值为(3, 10) , (9, 9), 盛水量为: 9 * (9-3) = 54 

分析
最直接的求法是计算两两计算一遍,求最大值。
但是明显的,有很多没必要的运算. 比如上图中的(1, 4), (2, 3) 与(10, 10) 的计算。

由于这是计算盛水量,所以主要取决于较小的数据,所以最大的数据再大,也没有起作用。
考虑到一般情况:
两个数字(i, ai), (j, aj), 他们的盛水量为 area =(j-i)*min(ai, aj),  取(k, ak) 使 i < k < j, 使面积比area更大。
不失一般性,设 ai <= aj,则min(ai, aj) = ai.
当ak <= ai 时, 由于  (k-i) * ak < area 和 (j-k) * ak < area(由于 k-i < j-i 和 j-k < j-i), 所以这种情况得到的结果肯定小于 area. 可以不考虑。

当 ak > ai 时
     ak 与ai的盛水量: (k-i)*ai < area, 所以这种情况也不需要考虑。
     ak与aj的盛水量: (j-k)*min(ak, aj) 由于 j-k < j-i 而 min(ak, aj) > ai, 不确定是否大于area. 
所以可得到简单算法:
  1. 取第一和最后的值为初始值,计算最近 盛水量。
  2. 往中间移动较小值的指针,录找比它大的数。
  3. 再计算盛水量,并比较大小。
  4. 重复2, 3.
算法代码

int maxArea(vector<int>& height) {                  int first = 0, end = height.size()-1;         int min = height[first] > height[end] ?  end :  first;         int maxArea = (end-first)*height[min];                   while(first < end){            //  cout<<first << " " << end << " min:" << min << endl;            // 移动最小值到下一个比当前最小值大的数。             if(first == min){                while(first < end && height[first] <= height[min]) first += 1;             }             if(end == min){                while(first < end && height[end] <= height[min]) end -= 1;             }            //  没有就退出            if(first >= end ) break;            // 计算盛水量比较            min = height[first] < height[end] ? first : end;            int area = (end-first) * height[min];             if(area > maxArea)                   maxArea = area;                        }           return maxArea;    }






0 0