1. leetcode 232 用栈实现队列
class MyQueue {
public:
stack<int> stIn;
stack<int> stOut;
MyQueue() {
}
// 入栈无返回,有参数
void push(int x) {
stIn.push(x);
}
// 出栈有返回,返回出栈的元素
int pop() {
//只有当stOut为空时,再从stIn中导入全部数
if (stOut.empty()) {
//倒入数据,直到stIn为空
while(!stIn.empty()) {
stOut.push(stIn.top());
stIn.pop();
}
}
//出栈的有元素,可以出栈,临时保存栈顶
int front = stOut.top();
stOut.pop();
return front;
}
int peek() {
int res = this->pop(); //直接使用已有的pop函数
stOut.push(res); // 因为pop函数弹出了元素res,所以添加回去
return res;
}
bool empty() {
return stOut.empty() && stIn.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
2. leetcode 225 用队列实现栈
//两个队列
class MyStack {
public:
queue<int> queue1;
queue<int> queue2;
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
queue2.push(x);
while (!queue1.empty()) {
queue2.push(queue1.front());
queue1.pop();
}
swap(queue1, queue2);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int r = queue1.front();
queue1.pop();
return r;
}
/** Get the top element. */
int top() {
int r = queue1.front();
return r;
}
/** Returns whether the stack is empty. */
bool empty() {
return queue1.empty();
}
};
// 一个队列
// 一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外)
// 重新添加到队列尾部,此时弹出的元素就是栈的顺序
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();
}
};
class MyStack {
public:
queue<int> que;
MyStack() {
}
void push(int x) {
que.push(x);
}
int pop() {
int size = que.size();
size--;
while (size--) {
que.push(que.front());
que.pop();
}
int res = que.front();
que.pop();
return res;
}
int top() {
return que.back();
}
bool empty() {
return que.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
3. leetcode 20 有效的括号
class Solution {
public:
bool isValid(string s) {
stack<int> st;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(') {
st.push(')');
} else if (s[i] == '{') {
st.push('}');
} else if (s[i] == '[') {
st.push(']');
//第三种情况 遍历字符串匹配过程中,栈已经为空,没有匹配的字符了,说明有括号没有找到对应的左括号 return false
//第二种情况 遍历字符串匹配过程中,发现栈里没有我们要匹配的字符,return false
} else if (st.empty() || st.top() != s[i]) {
return false;
} else {
st.pop();
}
}
//第一种情况 遍历完字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,return false 否则return true
return st.empty();
}
};
class Solution {
public:
bool isValid(string s) {
int size = s.size();
if (size % 2 == 1) {
return false;
}
unordered_map<char, char> pairs = {
{
')', '('},
{
']', '['},
{
'}', '{'}
};
stack<char> stk;
for (char ch : s) {
if (pairs.count(ch)) {
if (stk.empty() || stk.top() != pairs[ch]) {
return false;
}
stk.pop();
} else {
stk.push(ch);
}
}
return stk.empty();
}
};
4. leetcode 1047 删除字符串中的所有相邻重复项
// 相当于匹配
class Solution {
public:
string removeDuplicates(string s) {
stack<char> st;
for (auto i : s) {
if (st.empty() || i != st.top()) {
st.push(i);
} else (st.pop());
}
string res = "";
while (!st.empty()) {
res += st.top();
st.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
5. leetcode 150 逆波兰表达式求值
//使用栈
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> st;
int n = tokens.size();
for (int i = 0; i < n; i++) {
string& token = tokens[i];
if (isNumber(token)) {
st.push(atoi(token.c_str()));
} else {
int num2 = st.top();
st.pop();
int num1 = st.top();
st.pop();
switch (token[0]) {
case '+':
st.push(num1 + num2);
break;
case '-':
st.push(num1 - num2);
break;
case '*':
st.push(num1 * num2);
break;
case '/':
st.push(num1 / num2);
break;
}
}
}
return st.top();
}
bool isNumber(string& token) {
return !(token == "+" || token == "-" || token == "*" || token == "/");
}
};
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> st;
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
int num2 = st.top();
st.pop();
int num1 = st.top();
st.pop();
if (tokens[i] == "+") st.push(num1 + num2);
if (tokens[i] == "-") st.push(num1 - num2);
if (tokens[i] == "*") st.push(num1 * num2);
if (tokens[i] == "/") st.push(num1 / num2);
} else {
st.push(stoi(tokens[i]));
}
}
return st.top();
}
};
//使用数组模拟栈
class Solution {
public:
int evalRPN(vector<string>& tokens) {
int n = tokens.size();
vector<int> stk((n + 1) / 2);
int index = -1;
for (int i = 0; i < n; i++) {
string& token = tokens[i];
if (token.length() > 1 || isdigit(token[0])) {
index++;
stk[index] = atoi(token.c_str());
} else {
switch (token[0]) {
case '+':
index--;
stk[index] += stk[index + 1];
break;
case '-':
index--;
stk[index] -= stk[index + 1];
break;
case '*':
index--;
stk[index] *= stk[index + 1];
break;
case '/':
index--;
stk[index] /= stk[index + 1];
break;
}
}
}
return stk[index];
}
};
6. leetcode 239 滑动窗口最大值
//单调队列
class Solution {
private:
class MyQueue {
//单调队列(从大到小)
public:
deque<int> que; // 通过deque实现单调队列
//每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,相等则弹出
//同时pop之前判断队列当前是否为空
void pop(int val) {
if (!que.empty() && val == que.front()) {
que.pop_front();
}
}
//如果push的数值大于入口元素,那么将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止
//这样就保持队列里的数值是单调递减的了
void push(int val) {
while (!que.empty() && val > que.back()) {
que.pop_back();
}
que.push_back(val);
}
//查询当前队列里的最大值
int front() {
return que.front();
}
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue mq;
vector<int> res;
//先将前k个元素放进队列
for (int i = 0; i < k; i++) {
mq.push(nums[i]);
}
//存储结果
res.push_back(mq.front());
for (int i = k; i < nums.size(); i++) {
mq.pop(nums[i - k]); // 滑动窗口移除最前面元素
mq.push(nums[i]); //加入最后面元素
res.push_back(mq.front()); //记录最大值
}
return res;
}
};
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int n = nums.size();
deque<int> q;
for (int i = 0; i < k; ++i) {
while (!q.empty() && nums[i] >= nums[q.back()]) {
q.pop_back();
}
q.push_back(i);
}
vector<int> ans = {
nums[q.front()]};
for (int i = k; i < n; ++i) {
while (!q.empty() && nums[i] >= nums[q.back()]) {
q.pop_back();
}
q.push_back(i);
while (q.front() <= i - k) {
q.pop_front();
}
ans.push_back(nums[q.front()]);
}
return ans;
}
};
//优先队列
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;
}
};
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans; //存放答案,刚开始我把这个写成了vector<int> ans(nums.size()-k+1),然后多了好几个0……
deque<int> que; //双向队列,存放nums下标。这个容器有以下操作(看名字就知道作用了):
//front(),back(),push_back(value),push_front(value),pop_back(value),pop_front(value)
// 遍历数组中元素,right表示滑动窗口右边界
for(int right=0;right<nums.size();right++){
// 如果队列不为空且当前考察元素大于等于队尾元素,则将队尾元素移除。
// 直到,队列为空或当前考察元素小于新的队尾元素
while(!que.empty()&&nums[que.back()]<=nums[right]){
que.pop_back();
}
// 存储元素下标
que.push_back(right);
// 计算窗口左侧边界
int left=right-k+1;
// 当队首元素的下标小于滑动窗口左侧边界left时
// 表示队首元素已经不再滑动窗口内,因此将其从队首移除
while(que.front()<left){
que.pop_front();
}
// 由于数组下标从0开始,因此当窗口右边界right+1大于等于窗口大小k时
// 意味着窗口形成。此时,队首元素就是该窗口内的最大值
if(right+1>=k){
ans.push_back(nums[que.front()]);
}
}
return ans;
}
};