🌟Leetcode exercise record🌟 Stack & Queue 6 exercises
****刷题小结****
1.万事开头难,坚持刷题进度,加油,会越来越好
2.单调栈
3.逆序调用
4.动态数组,vector
6.循环 -数组处理:翻倍数组
7.求余,push前赋值
8.其他单调栈问题待练习,496,901,42,84
文章目录
232. 用栈实现队列
🙊 EASY
Q&A
使用栈实现队列的下列操作:
push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。
示例:
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false
说明:
说明:
你只能使用标准的栈操作 – 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)
-
💭Language: C++
**🍓🍓【WAY C++ 】双栈
class MyQueue {
public:
stack<int> inStack;
stack<int> outStack;
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
inStack.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
chek();
int cur = outStack.top();
outStack.pop();
return cur;
}
/** Get the front element. */
int peek() {
chek();
return outStack.top();
}
/** Returns whether the queue is empty. */
bool empty() {
return inStack.empty() && outStack.empty();
}
void chek(){
if(outStack.empty()){//栈outStack为空
while(!inStack.empty()){//栈inStack不为空
outStack.push(inStack.top());
inStack.pop();
}
}
}
};
225.用队列实现栈
🙊 EASY
Q&A
使用队列实现栈的下列操作:
push(x) – 元素 x 入栈
pop() – 移除栈顶元素
top() – 获取栈顶元素
empty() – 返回栈是否为空
注意:
只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。
💭Language: C++
**🍓🍓【WAY C++ 】双队列
需要两个队列配合,先将位于队列前部的元素统一移动到另一个队列中暂存,只留一个队尾元素,此时原本队尾的元素位于队首,即可取出。
front() 返回第一个元素
class MyStack {
public:
queue<int> q1;//主队列
queue<int> q2;//辅队列
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
q1.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int size = q1.size();
size--;
while(size--){
q2.push(q1.front());//将主队列q1中的元素除了最后一个元素都暂时放入辅队q2中
q1.pop();
}
int result = q1.front();//将此时q1中仅有的一个元素存为结果
q1.pop();
q1 = q2;
while(!q2.empty()){//清空辅助队列q2
q2.pop();
}
return result;
}
/** Get the top element. */
int top() {
return q1.back();
}
/** Returns whether the stack is empty. */
bool empty() {
return q1.empty();
}
};
155.最小栈
🙊 EASY
Q&A
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
例:
输入:
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
💭Language: C++
思路1:单栈 保存2个元素值:次入栈2个元素,一个是入栈的元素本身,一个是当前栈元素的最小值 如:入栈序列为2-3-1,则入栈后栈中元素序列为:2-2-3-2-1-1 用空间代价来换取时间代价
思路2: 双栈 辅助栈,与元素栈同步插入与删除,用于存储与每个元素对应的最小值。
**🍓🍓【WAY 1 C++ 】辅助栈min_stack
class MinStack {
public:
stack<int> x_stack;
stack<int> min_stack;
/** initialize your data structure here. */
MinStack() {
min_stack.push(INT_MAX);
}
void push(int x) {
x_stack.push(x);
min_stack.push(min(min_stack.top(),x));//最小栈压入栈顶元素和x_stack的入栈元素x的最小值
}
void pop() {
x_stack.pop();
min_stack.pop();
}
int top() {
return x_stack.top();
}
int getMin() {
return min_stack.top();
}
};
**🍓🍓【WAY2 C++ 】每次入栈保存2个元素,存储数据封装成pair<value, min>
class MinStack {
public:
/** initialize your data structure here. */
stack<pair<int,int>> x_stack;//pair<x,min>
MinStack() {
}
void push(int x) {
if(x_stack.empty()) x_stack.push(make_pair(x,x));
else x_stack.push(make_pair(x,min(x,x_stack.top().second)));
}
void pop() {
x_stack.pop();
}
int top() {
return x_stack.top().first;
}
int getMin() {
return x_stack.top().second;
}
};
20.有效的括号
🙊 EASY
Q&A
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 :
输入: “()”
输出: true
输入: “([)]”
输出: false
💭Language: C++
**🍓🍓【WAY 1 C++ 】辅助栈
注意switch的使用以及char c : s
char c : s
相当于JAVA的强for循环的语法结构。相当于C++的:
for( int i = 0; i < s.length(); i++)
class Solution {
public:
bool isValid(string s) {
stack<int> left;//借助栈,将左括号入栈
for(char c : s){//字符串的循环遍历
if(c == '(' || c == '[' || c == '{'){
left.push(c);
}
else {
if(!left.empty() && leftOf(c) == left.top()){//栈非空且右括号=栈首(左括号)
left.pop();//注意是pop
}
else {
return false;
}
}
}
return left.empty();
}
private:
char leftOf(char c){
if(c == ')') return '(';
if(c == '}') return '{';
return '[';
}
};
739.每日温度-- 数组中元素与下一个比它大的元素之间的距离
🙊 MEDIUM
Q&A
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例 给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
💭vector 容器类
vector():创建bai一个空的vector。
vector(itn nSize):创建一个vector,元素个数为nSize。
vector(int nSize, const T& t):创建一个vector,元素个数为nSize,且值均为t。
vector(const vector&):拷贝构造函数。
**🍓🍓【WAY 1 C++ 】单调栈
时间复杂度O(n) 空间复杂度O(n),n为温度列表的长度
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
//单调栈
stack<int> s;
int n = T.size();//温度列表的长度
vector<int> ans(n);//容器类,存储数组长度变化的动态数组
for(int i= 0 ;i < n ;i++){
while(!s.empty() && T[i] > T[s.top()]){//栈非空
int preIndex = s.top();
ans[preIndex] = i - preIndex;
s.pop();
}
s.push(i);
}
return ans;
}
};
**🍓🍓【WAY 2 C++ 】暴力解法 next???
维护一个数组 next 记录每个温度 在温度范围在 [30, 100] 内第一次出现的下标
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
int n = T.size();
vector<int> ans(n),next(101,INT_MAX);
for(int i = n - 1;i >= 0;--i){
//反向遍历温度列表。
//对于每个元素 T[i],在数组 next 中找到从 T[i] + 1 到 100 中每个温度第一次出现的下标
//将其中的最小下标记为 warmerIndex,则 warmerIndex 为下一次温度比当天高的下标。
int warmerIndex = INT_MAX;
for(int t = T[i] + 1;t < 100;++t){
warmerIndex = min(warmerIndex,next[t]);//Q
}
if(warmerIndex != INT_MAX){
ans[i] = warmerIndex - i;
}
next[T[i]] = i;
}
return ans;
}
};
503.下一个更大的元素2
🙊 MEDIUM
Q&A
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,*这个数字之后的第一个比它更大的数,*这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
示例 1:
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
注意: 输入数组的长度不会超过 10000。
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = nums.size();
vector<int> ans(n);
stack<int> s;
//逆序遍历的原因:由于顺序遍历,栈顶放置的是数组前面的值,也就是找到的大于自己的值的位置在自己的前面(左),题意要在自己的后面(右)找大于自己的值,所以逆序遍历更方便
for(int i = 2 * n - 1;i >= 0;i-- ){//将原始数组 “翻倍”,就是在后面再接一个原始数组
while(!s.empty() && s.top() <= nums[i % n]){//环形数组的效果,一般是通过求余 获得循环效果
s.pop();
}
ans[i % n] = s.empty() ? -1 : s.top();//多思考分析
s.push(nums[i % n]);
}
return ans;
}
};
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/next-greater-element-ii