zoukankan      html  css  js  c++  java
  • LeetCode题解——接雨水

    LeetCode题解——接雨水


    我的LeetCode代码集:https://github.com/cnamep001/LeetCode

    原题链接:https://leetcode-cn.com/problems/trapping-rain-water/description/




    题目描述:




    思路一:利用栈

    我们的栈stack中存储的是height数组的索引。如果指针cur指向的height数组中的值小于等于栈顶元素或者栈为空,我们就一直入栈,因此我们栈顶元素索引对应的height数组的值是整个栈中最小的。一旦指针cur指向的height数组中的值超过栈顶的元素索引对应的height数组的值,就代表栈顶元素有一个右边界。由于栈中的元素都是递减的,所以如果存在一个比栈顶元素大的栈中元素,则一定可以确定该横向区域内的盛水量。

    时间复杂度是O(n),空间复杂度是O(n)。

    实现代码:

    package com.m.trapping_rain_water.solution1;
    
    
    import java.util.Stack;
    
    public class Solution1 {
    
        public int trap(int[] height) {
            int n = height.length;
            int result = 0;
            if (n == 0 || n == 1) {
                return result;
            }
            int cur = 0;
            Stack<Integer> stack = new Stack<Integer>();
            while (cur < n) {
                while (!stack.isEmpty() && height[cur] > height[stack.peek()]) {
                    int top = stack.pop();
                    if (stack.isEmpty()) {
                        break;
                    }
                    int distance = cur - stack.peek() - 1;
                    int tempHeight = Math.min(height[cur], height[stack.peek()]) - height[top];
                    result += tempHeight * distance;
                }
                stack.push(cur);
                cur++;
            }
            return result;
        }
    
    }
    
    



    LeetCode解题报告:



    思路二:用双指针法

    (1)首先,找到能存水的左边界索引left和右边界索引right。

    对于左边界索引left是从数组头到数组尾方向看,第一次出现下降趋势的那个索引的位置。

    对于右边界索引right是从数组尾到数组头方向看,第一次出现下降趋势的那个索引的位置。

    (2)记录左边界和右边界的高度,分别记作leftHeight和rightHeight。显然,雨水数是由较低的边界所决定的。

    a.如果leftHeight小于等于rightHeight。

    如果此时满足left < right,说明左右边界还没有重合,尝试着令left加1。如果left位置能够存储雨水,则更新结果的值。如果left位置不能存储雨水,说明left位置的高度大于等于leftHeight,这时我们应该进入下一轮循环,更新leftHeight的值。

    b.如果leftHeight大于rightHeight

    如果此时满足left < right,说明左右边界还没有重合,尝试着令right减1。如果right位置能够存储雨水,则更新结果的值。如果right位置不能存储雨水,说明right位置的高度大于等于rightHeight,这时我们应该进入下一轮循环,更新rightHeight的值。

    该思路的时间复杂度是O(n)级别的,空间复杂度是O(1)级别的。


    实现代码:

    package com.m.trapping_rain_water.solution2;
    
    public class Solution2 {
    
        public int trap(int[] height) {
            int n = height.length;
            int result = 0;
            if (n == 0 || n == 1) {
                return result;
            }
            int left = 0;
            while (left < n - 1 && height[left + 1] >= height[left]) {
                left++;
            }
            int right = n - 1;
            while (right >= 1 && height[right - 1] >= height[right]) {
                right--;
            }
            while (left < right) {
                int leftHeight = height[left];
                int rightHeight = height[right];
                if (leftHeight <= rightHeight) {
                    while (left < right) {
                        left++;
                        if (height[left] < leftHeight) {
                            result += leftHeight - height[left];
                        } else {
                            break;
                        }
                    }
                } else {
                    while (left < right) {
                        right--;
                        if (height[right] < rightHeight) {
                            result += rightHeight - height[right];
                        } else {
                            break;
                        }
                    }
                }
            }
            return result;
        }
    
    }
    



    LeetCode解题报告:



    思路三:逐层累加法(会超时)

    首先遍历数组得到最高的柱子的高度maxHeight,我们总共需要计算maxHeight层。

    计算第i层时,我们需要将柱子的高度减去i,这里i从0开始计数。我们寻找每一层的左边界left和右边界right,在[left, right]之间高度小于等于0处,我们可以令能接的雨水数加1。

    这个思路的时间复杂度很明显,是O(maxHeight * n)级别的,其中n为height数组的长度。而对于空间复杂度,我们使用了一个新的数组newHeight记录各柱子高度减去i时的值,因此是O(n)级别的。


    实现代码:

    package com.m.trapping_rain_water.solution3;
    
    
    public class Solution3 {
    
        public int trap(int[] height) {
            int n = height.length;
            int result = 0;
            if (n == 0) {
                return result;
            }
            int maxHeight = height[0];
            for (int i = 1; i < n; i++) {
                if (height[i] > maxHeight) {
                    maxHeight = height[i];
                }
            }
            int[] newHeight = new int[n];
            for (int i = 0; i < maxHeight; i++) {
                for (int j = 0; j < n; j++) {
                    newHeight[j] = height[j] - i;
                }
                int left = 0;
                int right = n - 1;
                while (left < n && newHeight[left] <= 0) {
                    left++;
                }
                while (right >= 0 && newHeight[right] <= 0) {
                    right--;
                }
                for (int j = left; j <= right; j++) {
                    if (newHeight[j] <= 0) {
                        result++;
                    }
                }
            }
            return result;
        }
    
    }
    
    
  • 相关阅读:
    SupoSE 概述 Redmine
    tmux guake
    How to Install and Use Krugle Basic
    use webdevelop tools to delete domain specific cookies for ecommerical cps union effect
    执行hudson daemon的脚本
    python技巧26[python的egg包的安装和制作]
    HOWTO Modular Xorg
    ARC专题:再续 Xcode 4.2 中的Automatic Reference Counting (ARC)
    ARC专题:在Xcode 4.2中加入不支持ARC的源码
    Windows下的.NET+ Memcached安装
  • 原文地址:https://www.cnblogs.com/k-class/p/13830826.html
Copyright © 2011-2022 走看看