给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。说明:你不能倾斜容器,且 n 的值至少为 2。
快速一栏:
- 暴力拆解
- 双指针
感觉自己进步很大,第一反应就是双指针,但是对双指针的移动条件不是很明确,所以先上一轮暴力解法,时间复杂度O(N2),空间复杂度O(N)。
整体思路是在以i开头的所有框中找到最大的存入max[i]中,依次递推,再在max[i]中找最大值,简单粗暴,实际上也AC了:
public int maxArea(int[] height) {
int len = height.length;
int[] max = new int[len];
for(int i = 0; i < len; i ++) {
for(int j = i + 1; j < len; j ++) {
if((j - i) * Math.min(height[i], height[j]) > max[i])
max[i] = (j - i) * Math.min(height[i], height[j]);
}
}
int res = 0;
for(int val : max) {
if(res < val)
res = val;
}
return res;
}
当然,跑完的成绩并不优秀,再回到双指针的方法,双指针基本思想是:从两端开始,计算由left和right构成的矩形,之后将其中较矮的那边向对侧移动一格。原理是把不可能的选项排除掉。
假设我们把高的那个移动若干格,矮的不动,很容易理解得到的结果一定小于初始矩形的面积。所以虽然不知道高边不动的结果是是不是最优解,但矮边不动高边动的结果一定不是,所以可以排除。
public int maxArea(int[] height) {
int max = 0;
int left = 0;
int right = height.length - 1;//双指针
while(left < right) {
int temp = (right - left) * (Math.min(height[left], height[right]));
if(temp > max)
max = temp;
if(height[left] < height[right])
left ++;
else
right --;
}
return max;
}
网友评论