雙指針:42. 接雨水

 

 這題難度還是在想到辦法,實現並不困難

如何計算雨水呢,可以按列來算,統計每列能接的雨水

列的寬度已經確定了,能接雨水的高度等於

min(左側最高的高度,右側最高的高度)-本列高度

 

首先介紹雙指針,左側右側靠掃描來計算

class Solution {
    public int trap(int[] height) {
        int result=0;
        for(int i=0;i<height.length;i++)
        {
            if(i==0||i==height.length-1)
            {continue;}
            int heightLeft=height[i],heightRight=height[i];
            for(int left=i;left>=0;left--)
            {
                if(height[left]>heightLeft)
                {
                    heightLeft=height[left];
                }
            }
            for(int right=i;right<height.length;right++)
            {
                if(height[right]>heightRight)
                {
                    heightRight=height[right];
                }
            }

            int h=Math.min(heightLeft,heightRight)-height[i];
            if(h>0)
            {result+=h;}

        }
        return result;
      }
}

由於第一列和最後一列肯定接不到雨水,所以直接爲0

這樣的時間複雜度是On2

 

還可以用動態規劃來尋找左側右側,遞推方程如下:

 

 這裏需要注意邊緣情況的maxLeft,要記住一個列的最小maxLeft就是height[i],這樣意味着它是最高的,所以存不了水

class Solution {
    public int trap(int[] height) {
        int result=0;
        int[] maxLeft=new int[height.length];
        int[] maxRight=new int[height.length];
        for(int i=0;i<height.length;i++)
        {
            if(i==0)
            {maxLeft[i]=height[0];}
            else
            {
                maxLeft[i]=Math.max(height[i],maxLeft[i-1]);
            }
        }
        for(int i=height.length-1;i>=0;i--)
        {
            if(i==height.length-1)
            {maxRight[i]=height[i];}
            else
            {
                maxRight[i]=Math.max(height[i],maxRight[i+1]);
            }
        }
        for(int i=0;i<height.length;i++)
        {
            int h=Math.min(maxLeft[i],maxRight[i])-height[i];
            if(h>0)
            {result+=h;}
        }
        return result;
}
}

 

本題還有一種解法叫單調幀法,可以在O1的空間複雜度和On的複雜度完成這道題

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章