栈和队列的算法题
这里写目录标题
- <font color="FF00FF">1. 最小栈
- <font color="FF00FF">2. 栈的弹出压入序列
- <font color="FF00FF">3. 数组中第K个大的元素
- <font color="FF00FF">4. 逆波兰表达式求值
1. 最小栈
题目链接:https://leetcode.cn/problems/min-stack/
class MinStack {
public:stack<int> st;stack<int> min_stack;int val = 0;void push(int val) {st.push(val);if (min_stack.empty() || min_stack.top() >= val) {min_stack.push(val);}}void pop() {if (!st.empty()) {if (st.top() == min_stack.top()) {min_stack.pop();}st.pop();}}int top() {if (!st.empty()) {val = st.top();}return val;}int getMin() { return min_stack.top(); }
};
1. 首先创建两个栈,一个为正常栈(保存所有的进出栈数据)。
一个为最小栈(只有当数据为最小时,才会入栈)
2. 核心在于:入栈时,若数据最小,需要两个栈都要入栈,出栈时,如果出的数据为最小,需要更新最小栈。
首先入栈,正常栈的不管什么情况都入栈,但是如果是最小栈它必须为空才可以入栈,因为一开始栈一定为空,我们必须向最小栈里插入一个数据,接下来就是后面的数据必须比我的最小栈的栈顶元素小才入栈,因为最小栈就是拿当前数据的最小值,你都比我栈顶大了,那我就没有入栈的必要了。
出栈:栈不为空才能出栈,如果是正常栈就直接出栈,如果是最小栈,必须是最小栈的栈顶元素和正常栈的栈顶元素相同时才能出栈,因为最小栈的栈顶存的当前数据的最小元素。
取栈顶元素:题里的例子取的栈顶元素是st里的栈顶元素,所以判断一下,不为空取一下栈顶元素就好。
获取堆栈中的最小元素:取最小栈的栈顶。
2. 栈的弹出压入序列
题目链接:https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&&tqId=11174&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking
class Solution {public:bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {//入栈和出栈的元素个数必须相同if (pushV.size() != popV.size()) {return false;}int instack=0; //统计进栈的元素个数int outstack=0; //统计出栈的元素个数stack<int>s; // 用s来模拟入栈与出栈的过程while(outstack<popV.size()){// 如果s是空,或者栈顶元素与出栈的元素不相等,就入栈while(s.empty()||s.top()!=popV[outstack]){if(instack<pushV.size()){s.push(pushV[instack++]);}elsereturn false;}s.pop(); // 栈顶元素与出栈的元素相等,出栈outstack++;}return true;}
};
题目里的第一条就是两个序列的长度相同,所以不相同直接返回false,我们定义一个栈来模拟出栈和进栈的过程,首先就是出栈的元素个数要小于序列的弹出个数,因为outstack是从0开始的,如果s是空,或者栈顶元素与出栈的元素不相等,就入栈,因为相等就要出栈了,为空里面没有数据就一定要先入数据。之后循环判断跳出循环为true。
以示例1为例:
3. 数组中第K个大的元素
题目链接:https://leetcode.cn/problems/kth-largest-element-in-an-array/
class Solution {
public:int findKthLargest(vector<int>& nums, int k) {priority_queue<int> q(nums.begin(), nums.end());while (--k) {q.pop();}return q.top();}
};
用优先级队列的构造函数,也就是用迭代器初始化这段序列,因为优先级队列默认是大堆,也就是默认是降序,然后就while循环出堆,之后返回堆顶元素就可以了。
4. 逆波兰表达式求值
题目链接:https://leetcode.cn/problems/evaluate-reverse-polish-notation/
class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> s;for (size_t i=0; i < tokens.size(); i++) {string & str = tokens[i];if (!("+" == str || "-" == str || "*" == str || "/" == str)) {s.push(atoi(str.c_str()));} else {int right = s.top();s.pop();int left = s.top();s.pop();switch (str[0]) {case '+':s.push(left + right);break;case '-':s.push(left - right);break;case '*':s.push(left * right);break;case '/':s.push(left / right);break;}}}return s.top();}
};
首先定义一个栈,之后循环取vector中的的字符串,如果不是运算符就入栈,这里的atoi可以把字符串变成整形,“123”->123,c_str就是获取str中的字符串,如果是加减乘除,就取栈里的两个整数,之后用对应的运算符运算,最后返回栈顶元素就是想要的结果。
以示例一为例:
这就是示例1的过程,按照代码一看就知道了。