#Leetcode-11. 盛最多水的容器

题目:盛最多水的容器

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。

示例:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49

思路:双指针法

以i,j表示前后指针,H[i]表示位置i处的高度,n是输入的数据长度。S(i,j) = min(H[i],H[j]) * (j - i)是(i,j)对应的面积。
我们在由线段长度构成的数组中使用两个指针,一个放在开始,一个置于末尾。 
此外,我们使用变量 maxarea 来持续存储到目前为止所获得的最大面积。
在每一步中,我们会找出指针所指向的两条线段形成的区域,更新 maxareamaxarea,并将指向较短线段的指针向较长线段那端移动一步。

链接:https://leetcode-cn.com/problems/container-with-most-water/solution/sheng-zui-duo-shui-de-rong-qi-by-leetcode/
来源:力扣(LeetCode)

原理分析:

证明该方法并不会因为移动短指针而导致错过最大面积是双指针法的关键。
首先,对于:两指针一个放在开始,一个置于末尾 这一初始情况分析,由于两指针可以随意移动,因此正确情况包含于初始情况,安全;
现在用数学归纳法分析证明:假设第k个状态是安全的,那么完成移动小指针操作得到的第k+1个状态也是安全的
	对于H[i] < H[j]的情况,我们将 i 指针向右移动,这一操作损失了:S(i, j-1), S(i, j-2), ...,S(i, i+1) 的面积。
	因此如果能证明损失的情况均小于现存的所有情况即可证明:这一移动安全
	不妨用S(i , j') 代替损失的最大面积( i < j' < j)
	如果H[j'] <= H[i], 则S(i, j') = min(H(i), H(j')) * (j' - i) <= H(i) * (j' - i) < H(i) * (j - i) = S(i, j);
	如果H[j']  > H[i], 则S(i, j') = min(H(i), H(j')) * (j' - i) < H(i) * (j - i) = S(i, j);
	同理对于H[i] >= H[j] 的情况也可以证明(只是能否取等的区别)
故我们采用双指针法是安全的;

代码如下:

class Solution {
public:
    int maxArea(vector<int>& height) {
        int i =0, j = height.size()-1;
        int ans = 0, temp;
        while(i < j){
            temp = (j - i) * min(height[j], height[i]);
            ans = max(ans, temp);
            if(height[i] < height[j]){
                i++;
            }else{
                j--;
            }
        }
        return ans;
    }
};

你可能感兴趣的:(Leetcode刷题)