目录
一:基础回忆
栈 先进后出
进栈(栈的插入)push 出栈(栈的删除)pop
top栈顶:允许插入和删除的一端 栈底bottom 空栈
队列 先进先出
队头front:队首 允许删除的一端 队尾rear 空队列4
top back push pop empty front
二:题目
1.用栈实现队列
这里用栈来模拟队列只用一个栈是不行,要两个,一个进栈,一个出栈
一个栈为题目开始的队列所以第一个问就是将元素放入到栈中,并以个栈是辅助栈
实现 MyQueue 类:
push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除并返回元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。
class MyQueue{
public:
stack<int> stIn;
stack<int> stOut;//定义
MyQueue(){
}
void push(int x){
stIn.push(x);//加入一个元素
}
int pop(){
if(stOut.empty()){
//从stIn导入的数据直到stIn为空
while(!stIn.empty()){
stOut.push(stIn.top());//将进栈中的第一个元素加入到出栈
stIn.pop();//把进来栈的全部数都pop
}
}
int result = stOut.top();//获取第一个元素
stOut.pop();//把第一个元素弹出
return result;
}
//取队列的第一个元素
int peek(){
int res=this->pop();//直接调用上面的pop函数,调用类,在pop函数中弹出了,所以需要把他加进去
stOut.push(res);//添加回去res函数
return res;
}
bool empty(){
return stIn.empty()&&stOut.empty();
}
};
2.用队列实现栈
- push(x) -- 元素 x 入栈
- pop() -- 移除并返回栈顶元素
- top() -- 获取栈顶元素
- empty() -- 返回栈是否为空
若是用栈实现该题,就是很简单
class Solution{
public:
stack<int> st;
void push(x){
st.push(x);
}
int pop(){
int res = st.top();
st.pop(res);
return res;
int top(){
return st.top();
}
bool empty(){
return st.empty();
}
两个队列模拟栈
class MyStack{
public:
queue<int> que1;
queue<int> que2;//辅助队列,用来备份
MyStack(){
}
void push(int x){
que1.push(x);
}
int pop(){
int size = que.size();
size--;
while(size--){//将que1导入que2,但要留下最后一个元素
que2.push(que1.front());//注意队列 front 栈 top
que1.pop();
}
int result = que1.front();//留下的最后一个元素就是要返回的值
que1.pop();
que1=que2; //赋值
while(!que2.empty()){ //一定要清空que2
que2.pop();
}
return result;
}
int top(){
return que1.back()l
}
bool empty(){
return que1.empty();
}
};
只用一个队列
class MyStack{
public:
queue<int> que;//定义
MyStack(){
}
void push(int x){
que.push(x);//push(x) -- 元素 x 入栈
}
int pop(){//pop() -- 移除栈顶元素
int size=que.size();
size--;
while(size--){//从队列头部开始(除最后一个元素)
que.push(que.front());
que.pop;
}
int result=que.front();//此时的顺序就是栈的顺序
que.pop();
return result;
}
int top(){//top() -- 获取栈顶元素
return que.back();
}
bool empty(){//empty() -- 返回栈是否为空
return que.empty();
}
};
3.有效的括号(栈)
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。(这里就需要讨论见分析问题)
- 左括号必须以正确的顺序闭合。
- 注意空字符串可被认为是有效字符串。
代码中st.top==s[i] 已经包含了上面的两种情况(左和右匹配,左正确的顺序闭合)
由于于栈的结构特殊性,非常适合做对称匹配类的题目---------思考计算机的运行方式(自动补充括号)
分析问题: (1)括号多余:左边多余 右边多余
(2)括号不匹配
匹配度从中间断开,左右匹配,从栈顶开始所以用栈
class Solution{
public:
bool isValid(string s){
if(s.size()%2!=0)return false;
//开括号的长度是否匹配,若为奇数,则一定多余或少了
stack<char> 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(']');
//确认有哪些符号,并将对应的符号转换为右括号进栈
else if(st.empty()||st.top()!=s[i]) return false;
//栈里为空或者栈没有匹配的字符 则是错误的
else st.pop();// st.top==s[i] ,弹出元素,此时在匹配右括号(消消乐)
}
//前面的for判断栈已经空了
return st.empty();//empty==false
//遍历完所有的字符串,可是栈不为空,说明有相应的左括号与右括号不匹配 return false
//否则是true
}
};
有几个问题:为什么if else条件那么多,且都要放在一个for里,感觉想不到,害怕条件筛选错误
为什么没有返回true
4.删除字符串种所有相邻重复项(栈)
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
- 输入:"abbaca"
- 输出:"ca"
分析:存放遍历过后的元素,方便遍历当前元素时看是不是相邻相同的字母,若是就pop(消消乐)
class Solution{
public:
string removeDuplicates(string S){
stack<char> st;
for(char s:S){
if(st.empty()||s!=st.top()) st.push(s);
//这里一定要考虑空就像是考虑是否=0一样(=第一个数)
//保证前一个与后一个是否相同(>=2个数)易忽略
else st.pop();//s==st.top()
}
string result="";//定义新字符串
while(!st.empty()){//把栈中的元素放到字符串result中
result+=st.top();//记录到字符串
st.pop();//弹出
}
reverse(result.begin(),result.end());//调用函数反转
return result;
}
};
问题: 为什么这个地方可以直接在栈内相加 且定义字符串的方法很新。
若是直接用字符串做栈,省去了栈转化为字符串的操作(但不建议,这里主要是巩固栈,,详情见网站代码随想录)
5.前k个高频元素(综合)
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
- 输入: nums = [1,1,1,2,2,3], k = 2
- 输出: [1,2]
示例 2:
- 输入: nums = [1], k = 1
- 输出: [1]
分析:统计元素的出现概率(map) 对概率进行排序(优先级队列) 找到前k个高频元素(大顶堆取最上面的k个 ××,应该用小顶堆,统计最大的前k个)->这个问题需要去深入的学习几种建对的应用,筛选出来最好的
出现的专业名词:优先级队列 快排 map 大顶堆 小顶堆
详细代码见网站代码随想录 前k个高频元素
6.逆波兰表达式求值
输入:tokens = ["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
这个思考方式就很计算机 因为中缀运算(4+9/3)对于计算机不可能从左到右先运算9/3 后再倒回去,所以逆波兰可以实现
知识点stoll
1.stol 将字符串转化为long int
2.stoll 将字符串转化为long long int 字符串->整型
字符串string是“ ”代表字符串中的值,字符char类型用‘ ‘ 表示
class Solution {
public:
int evalRPN(vector<string>& tokens) {
// 力扣修改了后台测试数据,需要用longlong
stack<long long> st;
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
long long num1 = st.top();
st.pop();
long long num2 = st.top();
st.pop();
if (tokens[i] == "+") st.push(num2 + num1);
if (tokens[i] == "-") st.push(num2 - num1);
if (tokens[i] == "*") st.push(num2 * num1);
if (tokens[i] == "/") st.push(num2 / num1);
} else {
st.push(stoll(tokens[i]));
}
}
int result = st.top();
st.pop(); // 把栈里最后一个元素弹出(其实不弹出也没事)
return result;
}
};
问题:我没看到题目说要用longlong 的文字表述