📝前言说明:
本专栏主要记录本人的基础算法学习以及刷题记录,使用语言为C++。
每道题我会给出LeetCode上的题号(如果有题号),题目,以及最后通过的代码。没有题号的题目大多来自牛客网。对于题目的讲解,主要是个人见解,如有不正确,欢迎指正,一起进步!
🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C++学习笔记,C语言入门基础,python入门基础,python刷题专栏
🎀CSDN主页 愚润泽
题目
- [20. 有效的括号](#20. 有效的括号)
- [225. 用队列实现栈](#225. 用队列实现栈)
- [232. 用栈实现队列](#232. 用栈实现队列)
- [622. 设计循环队列](#622. 设计循环队列)
- [面试题03.05. 栈排序](#面试题03.05. 栈排序)
20. 有效的括号
经典的括号匹配题:利用栈。遇到左括号:入栈,遇到右括号:出栈
不过写代码时要注意:因为我们要让'(' 匹配 ')'
,所以遇到左括号时,直接将它对应的右括号入栈,后续可以直接字符比较判断。
cpp
class Solution {
public:
bool isValid(string s) {
stack<char> st;
for(auto ch : s)
{
if(ch == '('){
st.push(')'); // 需要匹配的
}
else if (ch == '['){
st.push(']');
}
else if (ch == '{'){
st.push('}');
}
else{
if( st.empty() || ch != st.top()){ // 这里要先判断栈是否为空
return false;
}
st.pop();
}
}
return st.empty();
}
};
225. 用队列实现栈

首先我们要了解栈的特点:先进后出,队列的特点:先进先出
因此,这道题的难点在于:如何让新入队的元素处于队头?
这道题给了我们两个队列,如果将一个队列当做主队列(即栈),另一个队列作为辅助队列,我们就可以利用辅助队列来改变新入队的元素的位置:
前提:每次操作前,辅助队列要为空。
思想:如果直接让新元素进主队列,那这个元素肯定是最后一个了,但是直接让新元素进辅助队列,那这个新元素就是辅助的第一个元素。所以我们先让新元素进入辅助队列,然后再把主队列(栈)里的元素依次出栈放入辅助队列,这样在辅助队列里新元素第一个出队列,而其他元素的出队列顺序与原来的主队列(栈)保持一致。这时候我们再交换辅助队列和主队列的身份。
cpp
class MyStack {
public:
queue<int> queue1;
queue<int> queue2;
MyStack() {
}
void push(int x) {
queue2.push(x); // 把新元素放到辅助队列
while(!queue1.empty()){
queue2.push(queue1.front()); // 依次将栈的元素放入辅助队列
queue1.pop();
}
swap(queue1, queue2);
}
int pop() {
int r = queue1.front();
queue1.pop();
return r;
}
int top() {
return queue1.front();
}
bool empty() {
return queue1.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();
*/
232. 用栈实现队列

只需要让一个栈进,一个栈负责出就行了。当一个栈的元素全部倒入另一个栈,这时候元素的出入顺序就会完全改变一次。(为了节约时间,我们只在outStack
里面元素彻底为空且遇到出栈需求时,才将inStack
的数据倒入`outStack)
cpp
class MyQueue {
public:
stack<int> inStack, outStack;
void in_to_out(){ // 倒转
while(!inStack.empty()){
outStack.push(inStack.top());
inStack.pop();
}
}
MyQueue() {
}
void push(int x) {
inStack.push(x);
}
int pop() {
if(outStack.empty()){
in_to_out();
}
int r = outStack.top();
outStack.pop();
return r;
}
int peek() {
if(outStack.empty()){
in_to_out();
}
return outStack.top();
}
bool empty() {
return inStack.empty() && outStack.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();
*/
622. 设计循环队列

下面解法以数组为例:
环形队列的关键在于:1,如何通过取模来达到走环的效果;2,如何判断队列满和空的情况。
对于循环:当一个数+1
时可能超出最大值,则需要%
来控制此数的大小任然在下标范围内;
对于判空:起始时front
指针和rear
指针都指向空;对于满,我们可以牺牲一个空间,即:当rear+1 == front
的时候为满(但注意rear + 1
要确保在数组下标内)。
下面做法以front
的后一位为第一个数据位为例:
cpp
class MyCircularQueue {
public:
// 用数组来模拟循环队列,让front指向的位置为空,front下一个位置才有节点
// front == rear时为空,当 rear + 1 == front 时为满
MyCircularQueue(int k)
{
capacity = k;
front = rear = 0;
que = vector<int> (k+1); // 比容量多开一个空间,则数组下标为[0, k](后续我们要让rear和front的下标在这个范围内,不然会越界)
}
bool enQueue(int value) {
if(isFull()){
return false;
}
rear = (rear + 1) % (capacity + 1);
que[rear] = value;
return true;
}
bool deQueue() {
if(isEmpty()){
return false;
}
front = (front + 1) % (capacity + 1);
return true;
}
int Front() {
if(isEmpty()){
return -1;
}
return que[(front + 1) % (capacity + 1)];
}
int Rear() {
if(isEmpty()){
return -1;
}
return que[rear];
}
bool isEmpty() {
return rear == front;
}
bool isFull() {
return ((rear + 1) % (capacity + 1)) == front;
}
private:
int front;
int rear;
int capacity;
vector<int> que;
};
/**
* Your MyCircularQueue object will be instantiated and called as such:
* MyCircularQueue* obj = new MyCircularQueue(k);
* bool param_1 = obj->enQueue(value);
* bool param_2 = obj->deQueue();
* int param_3 = obj->Front();
* int param_4 = obj->Rear();
* bool param_5 = obj->isEmpty();
* bool param_6 = obj->isFull();
*/
面试题03.05. 栈排序

这道题的题目表述不清楚,看示例可以发现,实际上是往栈里面插入元素,要保证插入后的顺序从栈底到栈顶是从大到小的。
我们只需要将每次要插入的元素和栈中已经有的元素作比较,找到合适的位置插入。
如:栈顶元素为t
,要插入元素为val
,如果val < t
,就直接入栈,否则,先让t
进入辅助栈,重复此过程,直到找到合适的位置插入,插入完后,把st2
的元素倒回来。
cpp
class SortedStack {
public:
SortedStack() {
}
void push(int val) {
while( !st1.empty() && st1.top() < val){
st2.push(st1.top()); // 把st1的元素暂存到st2
st1.pop();
}
st1.push(val);
// 把st2的元素倒回来
while(!st2.empty()){
st1.push(st2.top());
st2.pop();
}
}
void pop() {
if(!st1.empty()){
st1.pop();
}
}
int peek() {
if(!st1.empty()){
return st1.top();
}
return -1;
}
bool isEmpty() {
return st1.empty();
}
private:
stack<int> st1, st2;
};
/**
* Your SortedStack object will be instantiated and called as such:
* SortedStack* obj = new SortedStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->isEmpty();
*/
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!