给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个柱子高度图,计算按此排列的柱子,下雨之后能接多少雨水。(数组以外的区域高度视为0)
数据范围:数组长度
,数组中每个值满足
,保证返回结果满足
要求:时间复杂度
[3,1,2,5,2,4]
5
数组 [3,1,2,5,2,4] 表示柱子高度图,在这种情况下,可以接 5个单位的雨水,蓝色的为雨水 ,如题面图。
[4,5,1,3,2]
2
import java.util.*;
// @@@ 接雨水:双指针i,j初始位于两端, 水柱最高取min(a[i],a[j])
// i,j总移动小的那端,向中心移动直到碰到更高的桶边更新两端大小关系
// 直至i,j相遇
public class Solution {
public long maxWater (int[] arr) {
if (arr.length <= 1) return 0;
int i = 0, j = arr.length - 1, left = arr[i], right = arr[j];
long res = 0;
while (i < j) {
// 左端更矮
if (left <= right) {
while (i < j && arr[i] <= left) { // 遇到更低的,有水
res += left - arr[i];
i++;
}
if (i == j) break;
left = arr[i]; // 更新左端桶高
}
// 右端更矮 (处理同上)
else {
while (i < j && arr[j] <= right) {
res += right - arr[j];
j--;
}
if (i == j) break;
right = arr[j];
}
}
return res;
}
} public long maxWater (int[] arr) {
// 双指针 每次只计算一个格子的
int left=0;
int right=arr.length-1;
if(arr==null) return 0L;
long ans=0;
int maxL=0;
int maxR=0;
while(left<right){
//每次维护中间的最大边界
maxL=Math.max(maxL,arr[left]);
maxR=Math.max(maxR,arr[right]);
//判断哪边是较短的,统计水量
if(maxR>maxL){
ans=ans+(maxL-arr[left]);
left++;
}else{
ans=ans+(maxR-arr[right]);
right--;
}
}
return ans;
} public class Solution {
public long maxWater (int[] arr) {
// write code here
int length = arr.length;
int left = 0;
int right = length - 1;
long sum = 0L;
int lowMark = Math.min(arr[left], arr[right]);
while (left < right) {
if (arr[left] < arr[right]) {
left++;
if (arr[left] < lowMark) sum += lowMark - arr[left];
else lowMark = Math.min(arr[left], arr[right]);
} else {
right--;
if (arr[right] < lowMark) sum += lowMark - arr[right];
else lowMark = Math.min(arr[left], arr[right]);
}
}
return sum;
}
} import java.util.*;
public class Solution {
public long maxWater (int[] arr) {
// write code here
int l = 0, r = arr.length - 1;
int ans = 0, lmax = 0, rmax = 0;
while (l < r) {
//找左右两边最高的高度
lmax = Math.max(lmax, arr[l]);
rmax = Math.max(rmax, arr[r]);
//接雨水由最短的板子决定,计算雨量和移动短板
if (lmax < rmax) {
ans += lmax - arr[l];
l++;
} else {
ans += rmax - arr[r];
r--;
}
}
return ans;
}
} import java.util.*;
public class Solution {
/**
* max water
* @param arr int整型一维数组 the array
* @return long长整型
*/
public long maxWater (int[] arr) {
// write code here
int left = 0;
int right = 1;
int temp= 0;
int res = 0;
while(right<arr.length){
if(arr[left]>arr[right]){
temp+=arr[left]-arr[right];
right++;
}else{
res+=temp;
temp =0;
left = right;
right++;
}
}
if(temp == 0){
return res;
}
int rever= arr.length-2;
temp = 0;
right--;
while(rever>=left){
if(arr[rever]<arr[right]){
temp+=arr[right]-arr[rever];
rever--;
}else{
res +=temp;
temp=0;
right = rever;
rever--;
}
}
return res;
}
} class Solution {
public int trap(int[] height) {
int l=0,r=height.length -1,lnum=height[l],rnum=height[r],res=0;
while(l<r){
if(lnum<=rnum){
l++;
res += Math.max(lnum-height[l],0);
lnum = Math.max(lnum, height[l]);
}
else{
r--;
res += Math.max(rnum - height[r], 0);
rnum = Math.max(rnum, height[r]);
}
}
return res;
}
} import java.util.*;
public class Solution {
/**
* max water
* @param arr int整型一维数组 the array
* @return long长整型
*/
public long maxWater (int[] arr) {
// write code here
if (arr == null || arr.length <= 2) {
return 0;
}
int start = 0;
List<Count> valid = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
Count between = between(start, arr);
if (between.isValid()) {
valid.add(between);
}
if (between.isOver()) {
break;
}
start = between.getEnd();
}
long total = 0L;
for (Count count : valid) {
int min = Math.min(arr[count.getEnd()], arr[count.getStart()]);
for (int i = count.getStart() + 1; i < count.getEnd(); i++) {
total += min - arr[i];
}
}
return total;
}
public Count between(int start, int[] arr) {
Count count = new Count();
if (start >= arr.length - 2) {
count.setOver(true);
return count;
}
if (arr[start + 1] >= arr[start]) {
count.setValid(false);
count.setEnd(start + 1);
return count;
}
/*只剩下降趋势*/
count.setStart(start);
int flag = 1;
int mid = start;
while (mid < arr.length) {
if (mid == arr.length - 1) {
count.setOver(true);
return count;
}
/*下降趋势*/
if (arr[mid + 1] < arr[mid]) {
/*第一次下降 最小值修改 end修改 继续*/
if (flag == 1) {
count.setEnd(mid + 1);
}
/*第二次下降 有效区间 end修改*/
if (flag == 2) {
count.setValid(true);
count.setEnd(mid);
break;
}
}
/*等高*/
if (arr[mid] == arr[mid + 1]) {
count.setEnd(mid + 1);
}
/*增长趋势*/
if (arr[mid + 1] > arr[mid]) {
/*转折点*/
if (flag == 1) {
count.setEnd(mid + 1);
count.setValid(true);
flag = 2;
}
/*不可能出现 flag==2 且是增长趋势*/
count.setEnd(mid + 1);
}
mid++;
}
/*找寻更高的结束*/
if (count.isValid() && arr[count.getStart()] >= arr[count.getEnd()]) {
for (int i = count.getEnd(); i < arr.length; i++) {
if (arr[i] >= arr[count.getStart()]) {
count.setEnd(i);
break;
}
if (arr[i] >= arr[count.getEnd()]) {
count.setEnd(i);
}
}
}
return count;
}
public static class Count {
int start ;
int end;
boolean valid;
boolean over;
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
public boolean isOver() {
return over;
}
public void setOver(boolean over) {
this.over = over;
}
}
} import java.util.*;
public class Solution {
/**
* max water
* @param arr int整型一维数组 the array
* @return long长整型
*/
public long maxWater (int[] arr) {
// write code here
if (arr.length < 3) return 0;
int le = 0, ri = arr.length - 1;
int maxl = 0, maxr = 0, res = 0;
while (le < ri) {
maxl = Math.max(maxl, arr[le]);
maxr = Math.max(maxr, arr[ri]);
//
res += maxl < maxr ? maxl - arr[le++] : maxr - arr[ri--];
}
return res;
}
} import java.util.*;
public class Solution {
/**
* max water
* @param arr int整型一维数组 the array
* @return long长整型
*/
public long maxWater (int[] arr) {
// write code here
int V=0;
int[] leftmax=new int[arr.length];
int[] rightmax=new int[arr.length];
leftmax[0]=arr[0];
rightmax[arr.length-1]=arr[arr.length-1];
for(int i=1;i<=arr.length-1;i++){
leftmax[i]=Math.max(leftmax[i-1],arr[i]);
}
for(int i=arr.length-2;i>=0;i--){
rightmax[i]=Math.max(rightmax[i+1],arr[i]);
}
for(int i=0;i<=arr.length-1;i++){
if(leftmax[i]!=arr[i]&&rightmax[i]!=arr[i]){
V=V+Math.min(leftmax[i],rightmax[i])-arr[i];
}
}
return V;
}
} import java.util.*;
public class Solution {
/**
* max water
* @param arr int整型一维数组 the array
* @return long长整型
*/
public long maxWater (int[] arr) {
// write code here
int left = 0, right = arr.length - 1;
int sum = 0, height = 0;
while (left < right) {
if (arr[left] < arr[right]) {
height = Math.max(height, arr[left]);
sum = sum + height - arr[left];
left ++;
} else {
height = Math.max(height, arr[right]);
sum = sum + height - arr[right];
right--;
}
}
return sum;
}
} public long maxWater5 (int[] arr) {
long res = 0;
int i = 0, j = arr.length - 1;
while (i < j) {
long min = Math.min(arr[i], arr[j]); // 保存边界中的较小值
if (arr[i] < arr[j]) { // 若「左边界」较小,i指针右移计算蓄水量
while (arr[++i] < min) res += (min - arr[i]); // 一次性移动完毕,到第一个高度 ≥ 左边界的柱子
} else { // 同理,「右边界」对称移动
while (arr[--j] < min) res += (min - arr[j]);
}
}
return res;
}