[LeetCode][Array] 42. Trapping Rain Water

Problem: https://leetcode.com/problems/trapping-rain-water/

Solution1:
找出当前列的左边最高列和右边最高列,取较小的列与当前列进行比较,若当前列矮于较小列,则结果累加

class Solution {
    public int trap(int[] height) {
        int ans = 0;
        for(int i = 1; i < height.length -1; i++) {
            int max_left = 0, max_right = 0;
            
            for(int j = i-1; j>= 0; j--) {
                if(height[j] > max_left) {
                    max_left = height[j];
                }
            }
            
             for(int j = i+1; j < height.length; j++) {
                if(height[j] > max_right) {
                    max_right = height[j];
                }
            }
            
            int min = Math.min(max_left, max_right);
            ans += Math.max(0, min - height[i]);
        }
        return ans;
    }
}

时间复杂度为O(n2)
参考链接:https://leetcode-cn.com/problems/trapping-rain-water/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-8/

Solution2:
动态规划算法,存储从第 1 位到第 n-1 位的左右最大值

class Solution {
    public int trap(int[] height) {
        // dynamic programming
        int[] left = new int[height.length];
        int[] right = new int[height.length];
        for(int i = 1; i < height.length -1; i++) {
            left[i] = Math.max(left[i-1], height[i-1]);
        }
        
        for(int i = height.length - 2; i > 0; i--) {
            right[i] = Math.max(right[i+1], height[i+1]);
        }
        
        int ans = 0;
        for(int i = 1; i < height.length - 1; i++) {
            ans += Math.max(0, Math.min(left[i], right[i]) - height[i]);
        }
        return ans;
    }
}

时间复杂度降为O(n)

Solution3:
双指针法
设定 0 位和 n-1 位分别为两个指针,将两个指针的height进行比较,迭代较小的那一个
这个方法的好处是,可以不断改变迭代的方向(左→右或者右←左),而or循环只能进行一个方向的迭代

class Solution {
    public int trap(int[] height) {
       // two pointers
        int left = 0;
        int right = height.length -1;
        int max_left = 0;
        int max_right = 0;
        int ans = 0;
        while(left < right) {
            if(height[left] < height[right]) {
                if(height[left] >= max_left) {
                    max_left = height[left];
                } else {
                    ans += max_left - height[left];
                }
                left++;
            } else {
                 if(height[right] >= max_right) {
                    max_right = height[right];
                } else {
                    ans += max_right - height[right];
                }
                right--;
            }
        }
        return ans;
    }
}

Solution4:
采用压栈思想
若current的高度大于栈顶高度,则弹出栈顶(第 i 位),并计算第 i 位的储水量
储水量的计算方法为距离 x 高度,距离 = current - 当前栈顶 - 1,高度 = min(当前栈顶位的高度,current位的高度)

class Solution {
    public int trap(int[] height) {
       // 利用压栈思想
        int sum = 0;
        Stack<Integer> stack = new Stack<>();
        int current = 0;
        while (current < height.length) {
            while(!stack.empty() && height[current] > height[stack.peek()]) {
                int h = height[stack.peek()];
                stack.pop();
                if(stack.empty()) {
                    break;
                }
                int dis = current - stack.peek() - 1;
                int min = Math.min(height[current], height[stack.peek()]);
                sum += dis * (min - h);
            }
            stack.push(current);
            current++;
        }
        return sum;
    }
}

该方法初步理顺,还要加深理解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值