LeetCode42接雨水(C++)

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

暴力法优化(时间O(N),空间O(N))

算法思想:接得雨水总量等于每一个柱子所接雨水之和,每一个柱子能接到的雨水 = min(left_max[i], right_max[i]) - height[i], left_max[i]表示i左边的最大值,right_max[i]表示i右边的最大值

预先求得每一个元素height[i]对应的left_max和right_max,相比于暴力法在遍历每一个元素的for循环内部求解left_max和right_max,将时间复杂度从O(n的平方)降低到O(n)

class Solution {
public:
    //算法思想:接得雨水总量等于每一个柱子所接雨水之和,
    //每一个柱子能接到的雨水 = min(left_max[i], right_max[i]) - height
    int trap(vector<int>& height) {
        int len = height.size();
        if(len == 0) return 0;
        vector<int> left_max(len, 0);   //left_max[i]表示i左边的最大值(包含i)
        vector<int> right_max(len, 0);  //right_max[i]表示i右边的最大值(包含i)
        int ans = 0;

        //预先求得每一个元素height[i]对应的left_max和right_max,相比于暴力法在遍历每一个
        //元素的for循环内部求解left_max和right_max,将时间复杂度从O(n的平方)降低到O(n)
        left_max[0] = height[0];
        for(int i = 1; i < len; i++) {
            left_max[i] = max(height[i], left_max[i - 1]);
        }

        right_max[len - 1] = height[len - 1];
        for(int i = len - 2; i >= 0; i--) {
            right_max[i] = max(height[i], right_max[i + 1]);
        }

        for(int i = 0; i < len; i++) {
            ans += min(left_max[i], right_max[i]) - height[i];
        }

        return ans;
    }
};

双指针法(时间O(N),空间O(1))

算法思想:接得雨水总量等于每一个柱子所接雨水之和,每一个柱子能接到的雨水 = min(left_max[i], right_max[i]) - height[i], left_max[i]表示i左边的最大值,right_max[i]表示i右边的最大值

双指针法:相比于预先求得left_max和right_max数组,可分别维护left_max(从0开始,从左往右)和right_max(从len - 1开始,从右往左)指针, 当left_max <= right_max时, 从左往右依次计算每个柱子接水量,否则, 从右往左依次计算每个柱子接水量,直到二者相遇*/

class Solution {
public:
	//双指针
    /*算法思想:接得雨水总量等于每一个柱子所接雨水之和,每一个柱子能接到的雨水 = min(left_max, right_max) - height
    双指针法:相比于预先求得left_max和right_max数组,可分别维护left_max(从0开始,从左往右)
    和right_max(从len - 1开始,从右往左)指针,
    当left_max <= right_max时, 从左往右依次计算每个柱子接水量,
    否则, 从右往左依次计算每个柱子接水量,直到二者相遇*/
    int trap(vector<int>& height) {
        int len = height.size();
        if(len == 0) return 0;
        int left_max = height[0];         //left_max[i]表示i左边的最大值(包含i)
        int right_max = height[len - 1];  //right_max[i]表示i右边的最大值(包含i)
        int left = 0;
        int right = len - 1;
        int ans = 0;

        while(left < right) {
            if(height[left] <= height[right]) {
                //height[left] > left_max ? (left_max = height[left]) : ans += (left_max - height[left]); 
                left_max = max(height[left], left_max);
                ans += left_max - height[left]; 
                left++;
            }else {
                //height[right] > right_max ? (right_max = height[right]) : ans += (right_max - height[right]);
                right_max = max(height[right], right_max);
                ans += right_max - height[right];
                right--;
            }
        }

        return ans;
    }
};
发布了8 篇原创文章 · 获赞 0 · 访问量 120

猜你喜欢

转载自blog.csdn.net/oykotxuyang/article/details/105499345
今日推荐