题目:https://leetcode-cn.com/problems/container-with-most-water/description/
题目描述:
给定 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。
示例:
输入: [1,8,6,2,5,4,8,3,7] 输出: 49
思路:暴力枚举一下就能想到。但时间复杂度O(n^2)。所以要用动态规划,本题动态规划+双指针能得到O(n)时间复杂度。
动态规划
面积初始值令 j - i 最大,即取最大间隔,然后动态地交替地调整 i, 和 j 的取值,这样尽可能地每次试着增大 Min( h(i), h(j)) 值。只有这样,我们才有可能取到更大的面积值。
算法思路
-
面积最大值初始值设定 maxarea;
-
i, j 分别指向索引两头,动态交替地调整 i, j ,进而尝试取得较大的相对高度,这个调整的策略是关键,同时,更新目标函数即面积的最大值,如果大于maxarea,则更新;
-
直到 i >= j 为止;
-
返回最大值。
代码:
//暴力
class Solution {
public int maxArea(int[] height) {
int imax = 0;
int jmax = 0;
int temp = 0;
for(int i=0;i<height.length;i++){
for(int j=i+1;j<height.length;j++){
temp=(j-i)*Math.min(height[i],height[j]);
if(temp>jmax){
jmax=temp;
}
}
if(jmax>imax){
imax=jmax;
}
}
return imax;
}
}
//动态规划
public class Solution {
public int maxArea(int[] height) {
int maxarea = 0, l = 0, r = height.length - 1;
while (l < r) {
maxarea = Math.max(maxarea, Math.min(height[l], height[r]) * (r - l));
if (height[l] < height[r])
l++;
else
r--;
}
return maxarea;
}
}