题目

image.png

思路

  • 暴力解决
    • 求每一列能够保留多少水,因此我们会求左右最大列比当前列高的,然后选中两个中较小的一列,用它减去当前列就得到当前列所能够得到的积水。
    • image.png
  • 动态规划
    • 就是把暴力优化了,把每次获取最大最小值的用数组存起来,这样就能一次循环即可。
  • 单调栈
    • 通过计算当前左右列之间在某一层的面积,也就是计算局部的行面积,最终得到全部的积水面积

代码

  1. //1.列暴力
  2. public int trap(int[] height) {
  3. int ans = 0, size = height.length;
  4. for (int i = 0; i < size; i++) {
  5. int left = 0, right = 0;
  6. for (int j = i; j < size; j++) {
  7. left = Math.max(left, height[j]);
  8. }
  9. for (int j = i; j >= 0; j--) {
  10. right = Math.max(right, height[j]);
  11. }
  12. ans += Math.min(left, right) - height[i];
  13. }
  14. return ans;
  15. }
  16. //2.动态规划
  17. public int trap(int[] height) {
  18. int ans = 0, size = height.length;
  19. if (size <= 1) return ans;
  20. int[] left = new int[size], right = new int[size];
  21. left[0] = height[0];
  22. right[size - 1] = height[size - 1];
  23. for (int i = 1; i < size; i++) {
  24. left[i] = Math.max(height[i], left[i - 1]);
  25. }
  26. for (int i = size - 2; i >= 0; i--) {
  27. right[i] = Math.max(height[i], right[i + 1]);
  28. }
  29. for (int i = 1; i < size - 1; i++) {
  30. ans += Math.min(left[i], right[i]) - height[i];
  31. }
  32. return ans;
  33. }
  34. //3.单调栈
  35. public int trap(int[] height) {
  36. int size = height.length, ans = 0;
  37. Stack<Integer> stack = new Stack<>();
  38. for (int i = 0; i < size; i++) {
  39. while (!stack.isEmpty() && height[stack.peek()] < height[i]) {
  40. int cur = stack.pop();
  41. if (stack.isEmpty()) break;
  42. int l = stack.peek(), r = i;
  43. int h = Math.min(height[r], height[l]) - height[cur];
  44. ans += (r - l - 1) * h;
  45. }
  46. stack.push(i);
  47. }
  48. return ans;
  49. }

接雨水