1、用栈存并且匹配括号
2、用map存三种括号匹配情况
3、直接返回栈是否为空即可
class Solution {
public:
bool isValid(string s) {
map<char,char> res={
{'(',')'},{'[',']'},{'{','}'}
};
stack<char> stk;
for(int i=0;i<s.size();i++){
if(s[i]=='('||s[i]=='{'||s[i]=='[') stk.push(s[i]);
else if(stk.empty()) return false;
else if(res[stk.top()]==s[i]) stk.pop();
else return false;
}
return stk.empty();
}
};
栈中只保存左括号的下标,每遍历到右括号就出栈,比较当前最大合法长度
class Solution {
public:
int longestValidParentheses(string s) {
int maxans = 0;
stack<int> stk;
stk.push(-1);
for (int i = 0; i < s.length(); i++) {
if (s[i] == '(')
stk.push(i);
else {
stk.pop();
if (stk.empty())
stk.push(i);
else
maxans = max(maxans, i - stk.top());
}
}
return maxans;
}
};
1、用一个辅助栈存新数和栈底数之中的最小值,辅助栈大小和原栈大小一致,节省判断
2、先对栈进行判空,再取top值,否则报错
3、原栈压入可以单独提前,不用进行判断,注意不漏掉等于的情况
class MinStack {
public:
/** initialize your data structure here. */
stack<int> res,help;
MinStack() {
}
void push(int x) {
//缺少等于号的判断,导致提交一直溢出,可以把res.push提到前面
res.push(x);
//判空必须放前面,如果help为空则不判断第二个
if(help.empty()||x<=help.top())
help.push(x);
else if(!help.empty()&&x>help.top()){
int temp=help.top();
help.push(temp);
}}
void pop() {
if(!res.empty()&&!help.empty()){
res.pop();
help.pop();}
}
int top() {
return res.top();
}
int min() {
return help.top();
}
};
用一个栈记录正负号
class Solution {
public:
int calculate(string s) {
stack<int> ops;
ops.push(1);
int sign = 1,ret = 0,n = s.length(),i = 0;
while (i < n) {
if (s[i] == ' ') {
i++;
} else if (s[i] == '+') {
sign = ops.top();
i++;
} else if (s[i] == '-') {
sign = -ops.top();
i++;
} else if (s[i] == '(') {
ops.push(sign);
i++;
} else if (s[i] == ')') {
ops.pop();
i++;
} else {
long num = 0;
while (i < n && s[i] >= '0' && s[i] <= '9') {
num = num * 10 + s[i] - '0';
i++;
}
ret += sign * num;
}
}
return ret;
}
};
维持一个数字栈,不存标点符号,碰到加减号往里面塞正负数,碰到乘除号进行计算,最后累加栈中的数
class Solution {
public:
int calculate(string s) {
vector<int> stk;
char preSign = '+';
int num = 0;
int n = s.length();
for (int i = 0; i < n; ++i) {
if (isdigit(s[i]))
num = num * 10 + int(s[i] - '0');
if (!isdigit(s[i]) && s[i] != ' ' || i == n - 1) {
switch (preSign) {
case '+':
stk.push_back(num);
break;
case '-':
stk.push_back(-num);
break;
case '*':
stk.back() *= num;
break;
default:
stk.back() /= num;
}
preSign = s[i];
num = 0;
}
}
return accumulate(stk.begin(), stk.end(), 0);
}
};
1、有两种方法,单队列和双队列,单队列比较好理解
2、主要是入栈操作,每次入栈先入单队列,然后把之前所有元素弹出再重新入队,保证队头是刚入的栈顶数据
class MyStack {
public:
queue<int> q;
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
int n = q.size();
q.push(x);
for (int i = 0; i < n; i++) {
q.push(q.front());
q.pop();
}
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int r = q.front();
q.pop();
return r;
}
/** Get the top element. */
int top() {
int r = q.front();
return r;
}
/** Returns whether the stack is empty. */
bool empty() {
return q.empty();
}
};
用两个栈in和out,in只负责进,把in全部塞进out抽出成为一个公共函数,弹出和栈顶都从out拿,如果out是空的,就调用该函数,把in中的值全部挪到out中
class MyQueue {
private:
stack<int> inStack, outStack;
void in2out() {
while (!inStack.empty()) {
outStack.push(inStack.top());
inStack.pop();
}
}
public:
MyQueue() {}
void push(int x) {
inStack.push(x);
}
int pop() {
if (outStack.empty())
in2out();
int x = outStack.top();
outStack.pop();
return x;
}
int peek() {
if (outStack.empty())
in2out();
return outStack.top();
}
bool empty() {
return inStack.empty() && outStack.empty();
}
};
优先队列是最大堆,栈顶保存最大的元素,优先队列设置为数和位置的元组,每一次窗口都弹出最大值保存,优先队列用一个while弹出不在窗口的最大值
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int n = nums.size();
priority_queue<pair<int, int>> q;
for (int i = 0; i < k; ++i)
q.emplace(nums[i], i);
vector<int> ans = {q.top().first};
for (int i = k; i < n; ++i) {
q.emplace(nums[i], i);
while (q.top().second <= i - k)
q.pop();
ans.push_back(q.top().first);
}
return ans;
}
};
1、用一个string栈(用char栈会有逆序问题)和数字栈存字符串,对数字、字符、左右括号四种情况进行判断。
2、由于数字可能是两位数,所以数字不能直接入数字栈,用int型进位进行存储。
3、由于字符串取出时会存在逆序问题,所以不能挨个字符入栈,先暂时存入中间字符串。
4、结果字符串和中间字符串共用一个字符串即可。
class Solution {
public:
string decodeString(string s) {
stack<int> stkint;//数字栈
stack<string> stkstring;//用字符串栈代替字符栈,保证不会逆序
string tempstr="";//中间字符串和结果字符串共用一个
int num=0;
for(int i=0;i<s.size();i++){
if(isdigit(s[i]))
num=num*10+s[i]-'0';//不能直接入栈,因为有两位数,用int进位比字符串更方便
else if(isalpha(s[i]))
tempstr+=s[i];//暂时用字符串存,不要入字符栈,保证不会逆序
else if(s[i]=='['){
stkint.push(num);
num=0;
stkstring.push(tempstr);
tempstr="";
}
else if(s[i]==']'){
int count=stkint.top();
stkint.pop();
for(int j=0;j<count;j++)
stkstring.top()+=tempstr;//重复多次同时又能保证顺序
tempstr=stkstring.top();
stkstring.pop();
}
}
return tempstr;
}
};
1、用单调栈,来保存当前单调递减的温度序列。
2、栈内存温度序号值,不用存温度值,温度在数组T内,天数差=序号差num-temp
3、循环内不用while入栈
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
stack<int> stk;
vector<int> ans(T.size());
int num=0;
while(num<T.size()){
//不用入温度,入序列号
while(!stk.empty()&&T[num]>T[stk.top()]) {
int temp=stk.top();
stk.pop();
ans[temp]=num-temp;
}
//不用while入栈
stk.push(num++);
}
return ans;
}
};
1、用辅助栈实现,插入操作与压栈操作相同,弹出操作先将所有元素放入辅助栈,再弹出栈底元素,最后放入原栈
2、栈的操作用empty判空,不能用变量等于pop值。
class CQueue {
public:
stack<int> stk,stk1;
CQueue() {
}
void appendTail(int value) {
stk.push(value);
}
int deleteHead() {
if(stk.empty()) return -1;
//不能写stk.top!=NULL 要用empty进行判空,否则会报错
while(!stk.empty()) {
//不能直接用n等于栈的pop
int n=stk.top();
stk.pop();
stk1.push(n);
}
int ans=stk1.top();
stk1.pop();
while(!stk1.empty()) {
int n=stk1.top();
stk1.pop();
stk.push(n);
}
return ans;
}
};
1、队列题要用辅助队列,不能用辅助栈
2、用辅助队列存当前队列的最大值
3、压入元素时,先弹出辅助栈中所有小于当前值的元素
4、弹出队首元素时,判断该元素是否在辅助队列里,如果在,则同时弹出辅助队列队首元素
class MaxQueue {
public:
queue<int> q;
deque<int> help;
MaxQueue() {
}
int max_value() {
if(help.empty()) return -1;
return help.front();
}
void push_back(int value) {
//empty判断必须放前面,防止溢出
while(!help.empty()&&help.back()<value) help.pop_back();
q.push(value);
help.push_back(value);
}
int pop_front() {
if(q.empty()) return -1;
int a=q.front();
if(a==help.front()) help.pop_front();
q.pop();
return a;
}
};
1、用单调的双端队列存当前滑动窗口中的最大值的序号,而不是最大值本身
2、由于窗口的大小已经固定,不能用双指针法
3、每次弹出队尾小于当前值的元素
4、每次弹出队首不在当前滑动窗口序号范围内的元素
5、弹入当前值并且输出当前窗口最大值
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
//单调的双端队列
deque<int> temp;
vector<int> ans;
//i是数组nums的索引
for(int i=0;i<nums.size();i++)
{
//将当前滑动窗口的最大数置于双端队列队首,比较的是nums大小
while(!temp.empty()&&nums[i]>nums[temp.back()]) temp.pop_back();
//保证当前双端队列队首最大值是在滑动窗口内
while(!temp.empty()&&temp.front()<i-k+1) temp.pop_front();
//放入当前值
temp.push_back(i);
//输出当前滑动窗口内的最大值
if(i>=k-1) ans.push_back(nums[temp.front()]);
}
return ans;
}
};