https://leetcode-cn.com/problems/trapping-rain-water/
image.png

0位置和最后一个位置是放不了水的

法一:预处理数组

image.png

  • 把预处理数组求好,就知道每个i位置左边和右边的max了,就可以直接算然后累加了

    1. public int trap(int[] arr) {
    2. if (arr == null || arr.length < 3) {
    3. return 0;
    4. }
    5. int N = arr.length;
    6. int[] rMax = new int[N];
    7. rMax[N - 1] = arr[N - 1];
    8. for (int i = N - 2; i >= 0; i--) {
    9. rMax[i] = arr[i] > rMax[i + 1] ? arr[i] : rMax[i + 1];
    10. }
    11. int lMax = arr[0];
    12. int water = 0;
    13. for (int i = 1; i < N - 1; i++) {
    14. water += Math.max(Math.min(lMax, rMax[i + 1]) - arr[i], 0);
    15. lMax = Math.max(lMax, arr[i]);
    16. }
    17. return water;
    18. }

    法二:双指针

    image.png

  • Lmax和rMax去pk,

    • 若Lmax小(瓶颈),则先算L位置的水量, L++(因为对于L来说,现在左边的max是真实的, 而L右边的max现在还不确定会不会有比现在的rMax大的, 但至少是现在的rMax)
    • 若rMax小(瓶颈),先算R位置的水量, R—
      1. public int trap(int[] arr) {
      2. if (arr == null || arr.length < 3) {
      3. return 0;
      4. }
      5. int L = 1;
      6. int R = arr.length - 1;
      7. int LMax = arr[0];
      8. int RMax = arr[arr.length - 1];
      9. int water = 0;
      10. while (L <= R) {
      11. if (LMax <= RMax) {
      12. water += Math.max(LMax - arr[L], 0);
      13. LMax = Math.max(LMax, arr[L++]);
      14. } else {
      15. water += Math.max(RMax - arr[R], 0);
      16. RMax = Math.max(RMax, arr[R--]);
      17. }
      18. }
      19. return water;
      20. }
  • L < R 还是L <= R?

    • 想一下只有3个数的情况你就知道了