双指针-接雨水

接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨
之后能接多少雨水。

输入:整型数组
输出:整型变量
思路

  1. 一层一层的计算水量,会超出时间限制
  2. 按列求,分为三种情况,当前列与左右两边最大的列的较小值进行比较,只有当前列小于较小值,当前列才会接到水.也会超出时间限制
  3. 动态规划,不需要每次都求出左边和右边的最大值,可以将最大值存储到两个数组之中,就可以解决时间复杂度的问题
  4. 双指针,在第二个方法时,寻找左边的最大值其实可以并入计算节水量的循环中,但是寻找右边最大值不行,右边的需要从右往左遍历数组,所以可以使用双指针,来遍历数组

按列求:

class Solution {
    public int trap(int[] height) {
        //遍历数组,最左边和最右边的列都不可能存储水,所以存储水的列从索引为1开始,length-2结束
        int maxValue = 0;
        for(int i = 1;i < height.length - 1;i++){
            //找到左边最大值
            int maxLeft = 0;
            for(int m = 0;m < i;m++){
                maxLeft = Math.max(maxLeft,height[m]);
            }
            //找到右边最大值
            int maxRight = 0;
            for(int n = i + 1;n < height.length;n++){
                maxRight = Math.max(maxRight,height[n]);
            }
            //判断当前列与左边和右边的较小值进行比较,只有当当前值小于较小值时,才会接到水
            if(height[i] < Math.min(maxLeft,maxRight)){
                //计算当前列的接水量
                maxValue += Math.min(maxLeft,maxRight) - height[i];
            }
        }
        return maxValue;
    }
}

动态规划

class Solution {
    public int trap(int[] height) {
        //遍历数组,最左边和最右边的列都不可能存储水,所以存储水的列从索引为1开始,length-2结束
        int maxValue = 0;
         //找到左边最大值
        int[] maxLeft = new int[height.length];
        for(int i = 1;i < height.length - 1;i++){
            //最大值为前一个的最大值和前一个列值的较大值
            maxLeft[i] = Math.max(maxLeft[i - 1],height[i - 1]);
        }
        //找到右边最大值
        int[] maxRight = new int[height.length];
        for(int i = height.length - 2;i >= 0;i--){
           //最大值为后一个的最大值和后一个列值的较大值
            maxRight[i] = Math.max(maxRight[i + 1],height[i + 1]);
        }
        for(int i = 1;i < height.length - 1;i++){
        //判断当前列与左边和右边的较小值进行比较,只有当当前值小于较小值时,才会接到水
            if(height[i] < Math.min(maxLeft[i],maxRight[i])){
                //计算当前列的接水量
                maxValue += Math.min(maxLeft[i],maxRight[i]) - height[i];
            }
        }
        return maxValue;
    }
}

双指针时,左右最大值算上自己,比较简洁

class Solution {
    public int trap(int[] height) {
        //遍历数组,最左边和最右边的列都不可能存储水,所以存储水的列从索引为1开始,length-2结束
        int maxValue = 0;
        //定义左右指针
        int left = 0;
        int right = height.length - 
        1;
        //定义左右最大值
        int maxLeft = 0;
        int maxRight = 0;
        //遍历所有的值
        while(left < right){
            //此时的最大值已经算上当前列
            maxLeft = Math.max(height[left],maxLeft);
            maxRight = Math.max(height[right],maxRight);
            if(height[left] < height[right]){
                maxValue += maxLeft - height[left];
                left++;
            }else{
                maxValue += maxRight - height[right];
                right--;
            }
        }
        return maxValue;
    }     
}

你可能感兴趣的:(java,数据结构,算法)