classSolution{publicinttrap(int[] height){//核心思想:i处的积水等于左右峰值的最小值减去自身!!!//暴力法int n = height.length;int ans =0;for(int i =1;i < n-1;i++){//对于每一个元素,寻找它的左右峰值int max_left =0, max_right =0;for(int j = i;j >=0;j--){//注意j是从i开始!
max_left =Math.max(max_left, height[j]);}for(int j = i;j < n;j++){//注意j是从i开始!
max_right =Math.max(max_right, height[j]);}//i处的积水等于左右峰值的最小值减去自身!!!
ans +=Math.min(max_left, max_right)- height[i];}return ans;}}
2.动态规划
classSolution{publicinttrap(int[] height){//核心思想:i处的积水等于左右峰值的最小值减去自身!!!//动态规划 先找到每个位置的左右峰值int n = height.length, ans =0;int[] leftMax =newint[n];//记录每个元素的左边最大值int[] rightMax =newint[n];//记录每个元素的右边最大值
leftMax[0]= height[0];
rightMax[n-1]= height[n-1];for(int i =1;i < n;i++){
leftMax[i]=Math.max(height[i], leftMax[i-1]);
rightMax[n-i-1]=Math.max(height[n-i-1], rightMax[n-i]);}for(int i =0;i < n;i++){
ans +=Math.min(leftMax[i], rightMax[i])- height[i];}return ans;}}
3.单调栈
classSolution{publicinttrap(int[] height){//核心思想:i处的积水等于左右峰值的最小值减去自身!!!//单调栈int n = height.length, ans =0;Stack<Integer> st =newStack<>();for(int i =0;i < n;i++){while(!st.empty()&& height[i]> height[st.peek()]){int top = st.pop();if(st.empty())break;int left = st.peek();int currWidth = i - left -1;int currHeight =Math.min(height[left], height[i])- height[top];
ans += currWidth * currHeight;}
st.push(i);}return ans;}}
4.双指针
classSolution{publicinttrap(int[] height){//核心思想:i处的积水等于左右峰值的最小值减去自身!!!//双指针yyds!!//由于i处的积水总是由i左右峰值的最小值决定,因此可以优先找i左右峰值的最小值int n = height.length, ans =0;int left =0, right = n-1, leftMax =0, rightMax =0;while(left <= right){
leftMax =Math.max(leftMax, height[left]);
rightMax =Math.max(rightMax, height[right]);if(leftMax < rightMax){//左边峰值小,可以直接算left处的积水
ans += leftMax - height[left];
left++;}else{
ans += rightMax - height[right];
right--;}}return ans;}}
84.求柱状图最大面积
单调栈
classSolution{publicintlargestRectangleArea(int[] heights){//核心思想:以h[i]为高的矩形的宽等于i左右两边第一个小于h[i]之间的距离//单调栈int len = heights.length, area =0;Deque<Integer> st =newLinkedList<>();//添加哨兵int[] newHeight =newint[len+2];for(int i =0;i < len;i++){
newHeight[i+1]= heights[i];}
newHeight[0]=0;newHeight[len+1]=0;
len +=2;
st.push(newHeight[0]);for(int i =0;i < len;i++){while(newHeight[st.peek()]> newHeight[i]){//当栈顶元素比当前元素大时,说明以栈顶元素为高的矩形宽已经找到了int height = newHeight[st.pop()];//出栈int width = i - st.peek()-1;
area =Math.max(area, height*width);}
st.push(i);}return area;//核心思想:以h[i]为高的矩形的宽等于i左右两边第一个小于h[i]之间的距离//暴力法 超时// int n = heights.length, ans = 0;// for(int i = 0;i < n;i++){// int minHeight = heights[i];// int left = i, right = i;// while(left-1 >= 0 && heights[left-1] >= minHeight)// left--;// while(right+1 < n && heights[right+1] >= minHeight)// right++;// ans = Math.max(ans, minHeight*(right - left + 1));// }// return ans;}}
739.每日温度
单调栈
classSolution{publicint[]dailyTemperatures(int[] temperatures){//单调栈!/*什么时候需要用到单调栈:
当需要找左边或右边第一个比当前数大或小时立即想到单调栈!
*/int n = temperatures.length;int[] ans =newint[n];Deque<Integer> st =newLinkedList<Integer>();//Deque能当作栈而不是Queue!!!for(int i =0;i < n;i++){while(st.peek()!=null&& temperatures[i]> temperatures[st.peek()]){int j = st.poll();
ans[j]= i - j;}
st.push(i);}return ans;}}