栈和队列
文章目录
1.用栈实现队列
232.用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
-
void push(int x)
将元素 x 推到队列的末尾 -
int pop()
从队列的开头移除并返回元素 -
int peek()
返回队列开头的元素 -
boolean empty()
如果队列为空,返回true
;否则,返回false
class MyQueue { public: stack<int> sOut; stack<int> sIN; MyQueue() { } void push(int x) { sIN.push(x); } int pop() { if(sOut.empty()){ while(!sIN.empty()){ sOut.push(sIN.top()); sIN.pop(); } } int i = sOut.top(); sOut.pop(); return i; } int peek() { //不能把pop复制过来,因为不知道哪个先执行,如果其中一个执行了就把sIn设置为空 int j = this->pop(); sOut.push(j);//经过自己的pop会把第一个数删除 return j; } bool empty() { return sIN.empty() && sOut.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.用队列实现栈
225. 用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push
、top
、pop
和 empty
)。
实现 MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。
class MyStack {
public:
queue<int> q1;
queue<int> q2;
MyStack() {
}
void push(int x) {
if(q1.empty()){
q2.push(x);
swap(q1,q2);
}
else{
q2.push(x);
while(!q1.empty()){
q2.push(q1.front());
q1.pop();
}
swap(q1,q2);
}
}
int pop() {
int res = q1.front();
q1.pop();
return res;
}
int top() {
return q1.front();
}
bool empty() {
return q1.empty();
}
};
//leetcode 上有gif很清楚
3.有效括号
20. 有效的括号
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
class Solution {
public:
bool isValid(string s) {
if(s.size() == 0)return true;
if(s.size() % 2 != 0)return false;
stack<char>ss;
for(int i = 0;i < s.size();i++){
if(s[i] == '(')ss.push(')');
else if(s[i] == '{')ss.push('}');
else if(s[i] == '[')ss.push(']');
else{
if(ss.size() != 0 && s[i] == ss.top()){
ss.pop();
}
else{
return false;
}
}
}
if(ss.size() == 0)return true;
else return false;
}
};
4.删除字符串中的所有相邻重复项
1047. 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
1.stack
class Solution {
public:
string removeDuplicates(string s) {
stack<char>st;
for(int i = 0;i < s.size();i++){
if(st.size() == 0 || s[i] != st.top()){
st.push(s[i]);
}
else{
st.pop();
}
}
string ss ="";
while(!st.empty()){
ss += st.top();
st.pop();
}
reverse(ss.begin(),ss.end());
return ss;
}
};
2.string
class Solution {
public:
string removeDuplicates(string s) {
string ss;
for(int i = 0;i < s.size();i++){
if(ss.size() > 0 && s[i] == ss.back()){
ss.pop_back();
}
else{
ss += s[i];
}
}
return ss;
}
};
5.逆波兰
150. 逆波兰表达式求值
给你一个字符串数组 tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'
、'-'
、'*'
和'/'
。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<long int>st;
for(int i = 0;i < tokens.size();i++){
if(tokens[i] != "+" && tokens[i] != "-" && tokens[i] != "*" && tokens[i] != "/"){
st.push(stol(tokens[i]));
}
else {
long s1 = st.top();//stol可以将字符串转换为数字,转换完类型是long int
st.pop();
long s2 = st.top();
st.pop();
if(tokens[i] == "+")st.push(s1 + s2);
if(tokens[i] == "-")st.push(s2 - s1);
if(tokens[i] == "*")st.push(s2 * s1);
if(tokens[i] == "/")st.push(s2 / s1);
}
}
long int ss = st.top();
return ss;
}
};
*6. 滑动窗口最大值
239. 滑动窗口最大值
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
有点偏暴力算法时间超过限制
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int>q;
vector<int>v;
for(int i = 0;i < k;i++){
while(q.size() > 0 && nums[i] > nums[q.back()]){
q.pop_back();
}
q.push_back(i);
}
v.push_back(nums[q.front()]);
for(int i = k;i < nums.size();i++){
while(q.size() > 0 && nums[i] > nums[q.back()]){
q.pop_back();
}
q.push_back(i);
if(q.front() <= i - k){
q.pop_front();
}
v.push_back(nums[q.front()]);
}
return v;
}
};
7.前 K 个高频元素
347.前 K 个高频元素
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
1.哈希+排序
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int>mp;
for(int i = 0;i < nums.size();i++){
mp[nums[i]]++;
}
vector<int>v1;
for(auto val:mp){
v1.emplace_back(val.second);
}
sort(v1.begin(),v1.end());
vector<int>v2;
for(int i = v1.size() - k;i <v1.size();i++){
for(auto val:mp){
if(val.second == v1[i]){
v2.push_back(val.first);
mp.erase(val.first);
break;
}
}
}
return v2;
}
};
*2.小顶堆
class Solution {
public:
class myCompare{
public:
bool operator()(const pair<int,int>&l,const pair<int,int>&r){
return l.second > r.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int>mp;
for(int i = 0;i < nums.size();i++){
mp[nums[i]]++;
}
priority_queue<pair<int,int>,vector<pair<int,int>>,myCompare>p_q;
for(auto val:mp){
p_q.push(val);
if(p_q.size() > k){
p_q.pop();
}
}
vector<int>v(k);
for(int i = 0;i < k;i++){
v[i] = p_q.top().first;
p_q.pop();
}
return v;
}
};
*3.大顶堆
class Solution {
public:
//大顶堆
class mycomparison {
public:
bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
return lhs.second < rhs.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int, int> map;
for (int i = 0; i < nums.size(); i++) {
map[nums[i]]++;
}
priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;
for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
pri_que.push(*it);
}
vector<int> result(k);
for (int i =0; i < k;i++) {
result[i] = pri_que.top().first;
pri_que.pop();
}
return result;
}
};