传入一个数组,
右边减去左边索引的差值 为宽
左边和右边数值小的一个为高
求水桶容积最大,也就是求 宽*高 最大的情况
可以想象成要给坐标系,索引为x轴,数值为y轴,问:哪一个组合的封闭空间面积最大
解决办法一
(双指针法):使用两个指针 left
和 right
分别从数组的两端开始,逐步向中间移动。在每一步中,计算当前两个指针之间的水量,并更新最大水量。移动指针的策略是:如果左边的板较高,则移动右边的指针;否则,移动左边的指针。这种方法的关键在于每次移动较短的指针,以尽可能地增加水桶的容量。
时间复杂度为 O(n),其中 n 是数组的长度。因为只需要遍历一次数组即可找到最大水量。
效率较高,适用于大规模数据
let arr = [1,8,6,2,5,4,8,3,7]
//方法1
var maxArea = function (height) {
let max = 0;
let left = 0,right=height.length-1;
while(left<right){
const curArea = (right-left)*Math.min(height[left],height[right])
// 宽就是 右边索引和左边索引的差值
// 高就是 短的一条边,水桶能装多少水取决于最短的板
if(curArea>max){
max = curArea
}
if(height[left]>height[right]){
right--
}else{
left++
}
}
return max;
};
console.log(maxArea(arr)) //49
解决办法二
(暴力枚举法):使用两层嵌套的 for
循环遍历数组中的每一对元素,计算它们之间的水量,并更新最大水量。这种方法会检查所有可能的板对组合。
时间复杂度为 O(n^2),其中 n 是数组的长度。因为需要遍历数组中的每一对元素。
效率较低,适用于小规模数据。
let arr = [1,8,6,2,5,4,8,3,7]
// 方法二
function maxArea2(arr) {
let max= 0;
for(let i=0;i<arr.length;i++){
for(let j=i+1;j<arr.length;j++){
const area = (j-i)*Math.min(arr[i],arr[j])
if(area>max){
max = area
}
}
}
return max;
}
console.log(maxArea2(arr)) //49
总之,maxArea1
和 maxArea2
的主要区别在于实现方法和时间复杂度。在实际应用中,推荐使用双指针法(maxArea1
),因为它具有更高的效率。