接雨水
Contents
问题描述
Solutions
- 暴力法:遍历数组中的每一个元素,并分别向左、向右寻找比当前元素大的最大元素,两者取其小,减掉当前元素就是当前元素上面可存储的水量;将所有元素上面可存储的水量加起来就是最后的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
int res = 0; int n = height.length; for (int i = 0; i < n; i++) { int left = height[i]; for (int j = 0; j < i; j++) { if (height[j] > left) left = height[j]; } int right = height[i]; for (int j = i+1; j < n; j++) { if (height[j] > right) { right = height[j]; } } res += (Math.max(left,right)-height[i]); }
``
- 动态编程:用两个数组,分别将元素 i 左边和右边的最大元素存储起来即可。记得判断当前数组是否为空。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
int n = height.length; if (n == 0) return 0; int[] left = new int[n]; int[] right = new int[n]; int max = height[0]; for (int i = 0; i < n; i++) { if (height[i] > max) max = height[i]; left[i] = max; } max = height[n-1]; for (int i = n-1; i >=0 ; i--) { if (height[i] > max) { max = height[i]; } right[i] = max; } int res = 0; for (int i = 0; i < n; i++) { res += (Math.min(left[i],right[i])-height[i]); }
``
- 单调栈:单调递减栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
int n = height.length; if (n == 0) { return 0; } int res = 0; Deque<Integer> queue = new ArrayDeque<>(); for (int i = 0; i < n; i++) { while (!queue.isEmpty() && height[i] > height[queue.peek()]) { int top = queue.poll(); if (queue.isEmpty()) break; res += (i-queue.peek()-1)*(Math.min(height[i],height[queue.peek()])); } queue.offer(i); }
``
- 双指针:用两个指针分别记录左右两个方向的最大值,我们只需要考虑最大值更小的那一个方向即可!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
int n = height.length; if (n == 0) return 0; int left = 0, right = n-1; int i = 0, j = n-1; int res = 0; while (i < j) { if (height[i] < height[j]) { if (height[i] > height[left]) left = i; res = res + height[left] - height[i]; i++; } else { if (height[j] > height[right]) right = j; res = res + height[right] - height[j]; j--; } }
``
Author 段新朋
LastMod 2020-07-26