Offer 驾到,掘友接招!我正在参与 2022 春招打卡活动,点击查看活动详情。
一、题目描述:
- 盛最多水的容器-难度中等
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7] 输出:49 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1] 输出:1
提示:
n == height.length
2 <= n <= 10^5
0 <= height[i] <= 10^4
二、题目和思路分析:
这道题我觉得很容易,因为看完题目我是这么想的:
假设最大容积的两条垂线是height[i]和height[j]
则容器的值实际上就是x轴和短的那条线的乘积,即
(j-i)*height[i] 或 (j-i)*height[j]
然而我按着遍历的方法写完了代码,提交才发现测试用例给了一个巨长、巨大的数组。
都怪我没有认真看提示:
提示:
n == height.length
2 <= n <= 10^5
0 <= height[i] <= 10^4
看来遍历的方法不可行,说明要取更优解。
那么更优解有哪些特征呢?
我想了半天,想的头发都开始摇摇欲坠了,终于想到了那么一点点门道。
-
更优解肯定不是全部都进行计算再比较
-
更优解也需要把全部数据遍历一遍
-
更优解应该是预先判断结果是否会大于当前结果,有的计算,有的跳过
那么根据这些条件怎么想呢???
我又想了半天,头发终于坚持不住的时候,我想到了确定的值是x轴的长度,height.length,同时它是个变量,即height[j]-height[i]。
这时候我们可以用它去乘height[j]或height[i],不断循环即可同样遍历出所有数据。
大概是这么个意思,但我受限于一个不太聪明的大脑,又无法把每个细节每个逻辑想的清清楚楚明明白白。
啊啊啊,先写代码吧!!!
就这样,我写着,改着,想着,调试了一个多小时,终于写出来了!!!
还好思路是对的,不然淦到通宵也没结果。
三、代码:
代码实现如下:
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
// 假设最大容积的两条垂线是height[i]和height[j]
// 则容器的值实际上就是x轴和短的那条线的乘积,即
// (j-i)*height[i] 或 (j-i)*height[j]
// let max = 0
// for(let i = 0; i<height.length; i++){
// for(let j = i+1; j<height.length; j++){
// let h = height[i] > height[j]? height[j] : height[i]
// let sum = (j-i)*h
// max = sum > max? sum : max
// }
// }
// return max
// 遍历的方法不可行,说明要取更优解
// 更优解有哪些特征呢?
// 更优解肯定不是全部都进行计算再比较
// 更优解也需要把全部数据遍历一遍
// 更优解应该是预先判断结果是否会大于当前结果,有的计算,有的跳过
// 那么怎么想呢
// 确定的值是x轴的长度,height.length,同时它是个变量,即height[j]-height[i]。
// 这时候我们可以用它去乘height[j]或height[i],不断循环即可同样遍历出所有数据
let i = 0, j = height.length-1, minH = 0, max = 0
while(i < j){ // 两端开始向中间循环
if(height[i] < height[j]){ // 如果左边高度小于右边
minH = height[i] // minH取 height[i],左边向右移动
max = Math.max(((j-i) * minH), max)
i++
while(minH > height[i]){ // 如果移动后的高度还没当前高度高,那么不需要计算,继续移动
i++
}
}else{ // 如果右边高度小于左边,或两边相等
minH = height[j] // minH取 height[j],右边向左移动
max = Math.max(((j-i) * minH), max)
j--
while(minH > height[j]){ // 如果移动后的高度还没当前高度高,那么不需要计算,继续移动
j--
}
}
}
return max
};
四、总结:
今天是工作日,虽然不加班,但还是觉得时间不够用似的。
我本以为上一道题,也就是第十题就很难了,昨天搞了大半天也没搞出来,看了看别人的解题思路还是一头雾水,又看了好几遍才看出那么一点意思来,自己还是写不出。哪想到今天这道题也能写将近两个小时呢?
主要还是逻辑把握不住,想到一定深度大脑就像是卡死了,只能写一点看一点。另外细节还是容易漏掉,比如i++之后调用i,已经不是原先的i了,这点在我调试的时候,半天没看出来,还以为是自己思路不对。
嗐,世界上聪明的人那么多,可惜我不是其中一个。
加油吧!