本文主要是介绍【leetcode100-069到073】【栈】五题合集,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
【有效括号】
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
思路:
遇到左括号入栈,遇到右括号弹一个出来看是否匹配,全部走完看栈里是否还有没配对的左括号,如果以上步骤中任意时刻出问题,直接返回false,都没出问题则返回true。
class Solution {
public:bool isValid(string s) {vector<char> stk;for (int i = 0; i < s.size(); i++) {if (s[i] == '(' || s[i] == '{' || s[i] == '[') {stk.push_back(s[i]);}if (s[i] == ')') {if (stk.empty()||stk.back() != '(' )return false;stk.pop_back();}if (s[i] == '}') {if (stk.empty()||stk.back() != '{')return false;stk.pop_back();}if (s[i] == ']') {if (stk.empty()||stk.back() != '[')return false;stk.pop_back();}}return stk.empty();}
};
【最小栈】
设计一个支持 push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack
类:
MinStack()
初始化堆栈对象。void push(int val)
将元素val推入堆栈。void pop()
删除堆栈顶部的元素。int top()
获取堆栈顶部的元素。int getMin()
获取堆栈中的最小元素。
思路:
对于栈中任意元素,在它出栈前,比它更靠近栈底的元素是不可能发生变化的,那么我们使用一个辅助栈,记录当前元素及其下方所有元素中的最小值即可。
class MinStack {
public:stack<int> stk;stack<int> stk_min;MinStack() { stk_min.push(INT_MAX); }void push(int val) {stk.push(val);if (val < stk_min.top())stk_min.push(val);elsestk_min.push(stk_min.top());}void pop() {if (!stk.empty()) {stk.pop();stk_min.pop();}}int top() { return stk.top(); }int getMin() { return stk_min.top(); }
};
【字符串解码】
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string]
,表示其中方括号内部的 encoded_string
正好重复 k
次。注意 k
保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k
,例如不会出现像 3a
或 2[4]
的输入。
思路:
我们可以把每一对括号想象成一个递归函数的调用和返回,遇到左括号=一个新的调用,因此要把当前的“现场”保存下来,然后先去进行内层函数的计算,遇到右括号=内层函数返回,返回的时候要把之前保存的“现场”恢复,继续进行外层函数的计算。我们用一个栈来模拟现场的保存和恢复。
class Solution {
public:string decodeString(string s) {stack<int> numStk;stack<string> strStk;int num = 0;string cur = "";for (int i = 0; i < s.size(); i++) {//数字if (s[i] >= '0' && s[i] <= '9') {num = num * 10 + (s[i] - '0');}//括号else if (s[i] == '[') {numStk.push(num);num = 0;strStk.push(cur);cur = "";} else if (s[i] == ']') {int n = numStk.top();numStk.pop();string temp = strStk.top();strStk.pop();for(int i=0;i<n;i++) {temp += cur;}cur = temp;}//字母else {cur += s[i];}}return cur;}
};
【每日温度】
给定一个整数数组 temperatures
,表示每天的温度,返回一个数组 answer
,其中 answer[i]
是指对于第 i
天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0
来代替。
【柱状图最大矩形】
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
思路:
第一题的思路就是第二题思路的一部分,就放在一起讲了。
对第一题来说,要找的是比自身大的,因此在遍历时,遇到小的先存起来,只有当前元素比栈顶下标元素大时,才开始弹出栈内下标,直到栈内没有比当前元素更大的数时停止,并把当前元素入栈。第一题做到这里就够了,因为对任意元素我们只需要考虑它后面的元素,而最后留在栈内的元素就是没有合法的后续元素的,标0就可以。
第二题的逻辑和第一题相同,只是评判条件和第一题相反,因为要找的是第一个小于当前元素的,找到它就找到了当前矩形的右边界,而栈内元素是递增的,左边界就是栈顶元素下面的元素(其实不一定,可能会有非严格递增的情况,也就是栈顶和它下面的元素一样大,但因为本题找的是最大值,这样做对结果不会有影响,所以就不单独拿出来讨论了)。然后对最后剩余元素的处理不太一样,他们延伸出的矩形一直到数组边界都是合法的,所以我们把数组边界作为它的右边界来做计算,左边界的选取方法不变。
class Solution
{
public:vector<int> dailyTemperatures(vector<int>& temperatures) {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n=temperatures.size();vector<int> st(n,0);vector<int> ans(n,0);int j=0;for(int i=0;i<n;i++){while((j > 0) && temperatures[st[j]] < temperatures[i]){ans[st[j]]=i-st[j];j--;}j++;st[j]=i; }return ans;}
};
class Solution {
public:int largestRectangleArea(vector<int>& heights) {if (!heights.size())return 0;stack<int> stk;stk.push(-1);int maxArea = 0;int l = 0, r = 0, curHeight = 0, curArea = 0;for (int i = 0; i < heights.size(); i++) {//空栈或能延伸if (stk.top() == -1 || heights[i] >= heights[stk.top()]) {stk.push(i);continue;}//把能确定面积的都算了并退栈while (stk.top() != -1 && heights[i] < heights[stk.top()]) {curHeight = heights[stk.top()];stk.pop();curArea = (i - stk.top() - 1) * curHeight;maxArea = max(maxArea, curArea);}stk.push(i);}//处理还没能出栈的//还有while (stk.top() != -1) {curHeight = heights[stk.top()];stk.pop();curArea = (heights.size() - stk.top() - 1) * curHeight;maxArea = max(maxArea, curArea);}return maxArea;}
};
这篇关于【leetcode100-069到073】【栈】五题合集的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!