记录前两天写的一题,两种方法。
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
这个题本身是单调栈的题,但是我试着用双指针完成,测出来居然比单调栈要快?哈哈哈
方法一 : 单调栈
单调栈的实现真的太过神奇,我们只需要会用就可以,完全凭借自己去想很难想到。
用一个递减的单调栈去描述当前最高的柱子,如果没有更高的就和能触及到的最矮的算最大面积,算是暴力的一个优化,具体看代码:
class Solution {
public int trap(int[] nums) {
int n = nums.length;
Stack<Integer> stk = new Stack<>();
int ans = 0, cnt = 0;
while (cnt < n) {
while (!stk.empty() && nums[cnt] > nums[stk.peek()]) {
int peek = stk.pop();
if (stk.empty()) break;
int distance = cnt - 1 - stk.peek();
int minban = Math.min(nums[cnt], nums[stk.peek()]) - nums[peek];
ans += distance * minban;
}
stk.push(cnt++);
}
return ans;
}
}
时间复杂度 O(n)
方法二: 双指针
因为水往低处流,临时想到能不能把最高的柱子找出来,然后分别从左右边遍历到中间最高的柱子,若能挡住水,则计数。具体实现看代码,个人认为这种方法非常好理解,代码也很简单。
class Solution {
public int trap(int[] nums) {
int n = nums.length;
if (n == 0) return n;
int highest = 0;
int ans = 0;
for (int i = 1; i < n; i++) {
if (nums[i] > nums[highest]) highest = i; //highest最大值下标
}
int i = 0, j = 0;
while (j <= highest) {
if (nums[i] > nums[j]) {
ans += nums[i] - nums[j];
j++;
} else {
i=j;
j=i+1;
}
}
i=n-1;
j=i-1;
while (j>=highest){
if (nums[i] > nums[j]) {
ans += nums[i] - nums[j];
j--;
} else {
i=j;
j=i-1;
}
}
return ans;
}
}
时间复杂度 O(n)
欢迎批评指正~