Leetcode42. Trapping Rain Water
关键词:DP,stack,2pointer
首先是暴力解法:
class Solution { public int trap(int[] height) { int leftmax = 0; int rightmax = 0; int ans=0; for(int i=0;i<height.length;i++){ leftmax=0;rightmax=0; int tempmax=0,p=i; if(i>0){ p=i-1;tempmax=0; while(p>=0){ tempmax = Math.max(tempmax,height[p--]); } leftmax=tempmax; } if(i<height.length-1){ p=i+1;tempmax=0; while(p<=height.length-1){ tempmax = Math.max(tempmax,height[p++]); } rightmax=tempmax; } if(rightmax>height[i]&&leftmax>height[i]){ ans+=Math.min(rightmax,leftmax)-height[i]; } } return ans; } }
128ms , 2.99%。太垃圾了…不行。
然后看了discuss后思路2:
DP:用很简单的DP去处理左右的max的计算,存到数组里,这样只需遍历3遍,时间复杂度从O(n^2)降到了O(n)。
如:leftmax[i]表示,第i个元素左边最大的值。更新:leftmax[i]=max(leftmax[i-1],height[i-1])。
rightmax相同,然后再遍历一遍得到结果即可。
其实这道题并不难,自己开始的思路已经很接近了。
class Solution { public int trap(int[] height) { int[] leftmax = new int[height.length]; int[] rightmax = new int[height.length]; for(int i=1;i<height.length;i++){ leftmax[i] = Math.max(leftmax[i-1],height[i-1]); } for(int i=height.length-2;i>=0;i--){ rightmax[i] = Math.max(rightmax[i+1],height[i+1]); } int ans=0; for(int i=0;i<height.length;i++){ if(rightmax[i]>height[i]&&leftmax[i]>height[i]) ans+=Math.min(leftmax[i],rightmax[i])-height[i]; } return ans; } }
17ms,20.66%。但是也并不快诶。
思路3,stack,也很巧妙,遇到这种两边夹逼的,也可以往stack上想。自己没完全搞明白,下面是个错误但是接近的答案:
class Solution { public int trap(int[] height) { if(height==null||height.length==0) return 0; Stack<Integer> stack = new Stack<>(); stack.push(0); int ans=0; for(int i=1;i<height.length;i++){ if(height[i]>height[stack.peek()]){ int mid = stack.pop(); if(!stack.empty()){ ans+=(Math.min(height[i],height[stack.peek()])-height[mid])*(i-stack.peek()-1); }else{ stack.push(mid); } stack.push(i); }else if(height[i]<height[stack.peek()]){ stack.push(i); } } return ans; } }
Your input
[0,1,0,2,1,0,1,3,2,1,2,1]
Output
3
Diff
Expected
6
还有思路4,two pointer,有空可以看看。
DP即可。stack更好,能用two pointer更更好。

浙公网安备 33010602011771号