赞
踩
注:按照代码随想录的刷题指南进行,自己总结补充,以加深印象
参考链接:https://leetcode-cn.com/circle/article/wGp7Y9/
题目来源:力扣(LeetCode)
单调栈顾名思义,利用栈的结构和特性解决问题。
相当于用空间换时间
关键点在于栈内元素的单调顺序, 以及栈内存放的元素。
使用时机:
通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。
vector<int> dailyTemperatures(vector<int>& temperatures) { stack<int> st;//存放的是索引 vector<int> result(temperatures.size(), 0); st.push(0); for(int i = 1; i < temperatures.size(); i++){ int now = temperatures[i]; while(!st.empty() && now > temperatures[st.top()]){ result[st.top()] = i - st.top(); st.pop(); } st.push(i); } return result; }
for(int i = 1; i < nums.size() * 2; i++){
int index = i%nums.size();
}
int trap(vector<int>& height) { stack<int> st; int ans = 0; st.push(0); for(int i = 1; i < height.size(); i++){ int num = height[i]; while(!st.empty() && num > height[st.top()]){ //栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。 int mid = height[st.top()]; st.pop(); if(!st.empty()){ int h = min(height[st.top()], num) - mid;//记得要减去mid, 左边的柱子并不pop出来 int w = i - st.top() - 1; ans += (h * w); } //如果相等,不做处理 } st.push(i); } return ans; }
时间O(n^2), 超出时间限制, int trap(vector<int>& height) { int left = 0, right = 0; int ans = 0; //第一个和最后一个柱子不能接水,不计算 for(int i = 1 ; i < height.size() - 1; i++){ left = right = height[i]; for(int k = i - 1; k >= 0; k--){ if(height[k] > left) left = height[k]; } for(int k = i + 1; k < height.size(); k++){ if(height[k] > right) right = height[k]; } ans += min(left, right) - height[i]; } return ans; }
优化: 为了得到两边的最高高度,使用了双指针来遍历,每到一个柱子都向两边遍历一遍,这其实是有重复计算的。我们把每一个位置的左边最高高度记录在一个数组上(maxLeft),右边最高高度记录在一个数组上(maxRight)。这样就避免了重复计算,这就用到了动态规划。
动态规划:当前位置,左边的最高高度是前一个位置的左边最高高度和本高度的最大值。
即从左向右遍历:maxLeft[i] = max(height[i], maxLeft[i - 1]);
从右向左遍历:maxRight[i] = max(height[i], maxRight[i + 1]);
int trap(vector<int>& height) { int ans = 0; vector<int> leftHeight(height.size(), 0); vector<int> rightHeight(height.size(), 0); leftHeight[0] = height[0]; for(int i = 1; i < height.size(); i++){ leftHeight[i] = max(leftHeight[i - 1], height[i]); } int size = height.size(); rightHeight[size - 1] = height[size - 1]; for(int i = size - 2; i >= 0; i--){ rightHeight[i] = max(rightHeight[i + 1], height[i]); } for(int i = 1; i < size - 1; i++){ ans += min(leftHeight[i] , rightHeight[i]) - height[i]; } return ans; }
int largestRectangleArea(vector<int>& heights) { stack<int> st; int area = 0; int best = 0; heights.insert(heights.begin(), 0); heights.push_back(0); st.push(0); for(int i = 1; i < heights.size(); i++){ int num = heights[i]; while(!st.empty() && num < heights[st.top()]){ int mid = heights[st.top()]; st.pop(); if(!st.empty()){ int left = heights[st.top()]; area = mid * (i - st.top() - 1); if(area > best) best = area; } } st.push(i); } return best; } };
1、单调栈的使用时机
2、循环数组的处理 503题
3、分析题目就是一个抽丝剥茧的过程,找到最本质的问题,然后在找和本质问题的特殊性
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。