a[left, right] 是一个水槽, 递归的看,可能中间存在某个mid, a[left, mid]也是水槽,a[mid, right]也是水槽,那么怎么解决这个递归问题呢?
本人的方法是用一把刀横着去切水槽:sum表示水槽容积
1.假设用一把 刀 横着去切这个水槽 a[left, right] 那么从哪边开始切呢?当然是从小的一边开始切
if a[left] <= a[right] 从左边向右切一刀水槽:
怎么切?没有遇到挡住的障碍,说明可以装水,一路切过去,同时计算sum += a[left] - a[l]
if a[left] > a[right] 从右边向左切一刀水槽:
怎么切?没有遇到挡住的障碍,说明可以装水,一路切过去,同时计算sum += a[right] - a[r]
2.切完一次,left 和 right 重新移到递归小水槽的两边, 于是又递归成了切水槽问题(计算水槽容积问题),返回 1 计算,直到 l = r
整个数组遍历一次,时间复杂度:O(n) 空间复杂度O(1)
class Solution {
public:
/**
* max water
* @param arr int整型vector the array
* @return long长整型
*/
long long maxWater(vector<int>& arr) {
int l =0, r = arr.size()-1;
long long sum=0; //注意要long long 否则很可能加法溢出
while(l<r){//左右不等,没砍完
if(arr[l] <= arr[r]){ // 左边比右边小,从左边开始砍
int left = arr[l]; //基准
while(l+1<r && arr[l+1]< left){ //如果右边一个位置比基准矮,刀无阻碍
sum += (left-arr[l+1]); //刀下方可以装水
l++;
}
l++; //刀遇到到第一个碰瓷(碰刀)的柱子
}
else{ //否则从右边开始切
int right = arr[r]; //以右边最低为基准
while(r-1>l && arr[r-1] < right){//如果左边一个位置比基准矮,刀无阻碍
sum += (right -arr[r-1]); //刀下方装水
r--;
}
r--; //向左移移到第一个碰瓷(碰刀)的柱子
}
}
return sum;
}
};
转载牛客网用户 千帆L