LeetCode刷题day29

简介: LeetCode刷题day29

今日刷题重点—栈和队列

232. 用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):


实现 MyQueue 类:


void push(int x) 将元素 x 推到队列的末尾

int pop() 从队列的开头移除并返回元素

int peek() 返回队列开头的元素

boolean empty() 如果队列为空,返回 true ;否则,返回 false

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

思路分析

栈存储元素的顺序和队列正好是相反的,栈:先进后出,队列:先进先出.

所以模拟队列时需要两个栈,一个用于push输入元素:stIn,一个用于pop()操作:stOut.


push():直接将元素push到stIn即可.

pop():先判断stOut是否为空,如果为空则现将stIn的元素移动到stOut中,然后再进行pop()操作 如果不为空,则直接进行弹出操作==> (stOut.top(),stOut.pop())

peek():可以利用pop()获得元素,再将其压入到队列中.

empty():需要判断stIn和stOut是否都为空.


图解:


image.gif

class MyQueue {
public:
  stack<int> stIn;
  stack<int> stOut;
    MyQueue() {
    }
    void push(int x) {
      stIn.push(x);
    }
    int pop() {
    if(stOut.empty()){
      while(!stIn.empty()){
        stOut.push(stIn.top());
        stIn.pop();
      }
    }
    int result = stOut.top();
    stOut.pop();
    return result;
    }
    int peek() {
    int result = this->pop();
    stOut.push(result); 
    return result;
    }
    bool empty() {
    return stIn.empty()&&stOut.empty();
    }
};

225. 用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。


实现 MyStack 类:


void push(int x) 将元素 x 压入栈顶。

int pop() 移除并返回栈顶元素。

int top() 返回栈顶元素。

boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

实例

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]


思路分析

队列是先进先出的规则,把一个队列中的数据导入另一个队列中,数据的顺序并没有变,并没有变成先进后出的顺序。

所以用栈实现队列, 和用队列实现栈的思路还是不一样的.


但是依然还是要用两个队列来模拟栈,只不过没有输入和输出的关系,而是另一个队列完全用又来备份的!


具体实现: 用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。


图解:


image.gif


参考代码1

class MyStack {
public:
  queue<int> Q1;
  queue<int> Q2;
    MyStack() {
    }
    void push(int x) {
      Q1.push(x);
    }
    int pop() {
      int size = Q1.size();
      size--;
      while(size--){//弹出size-1个元素到Q2,剩下的那个就是要返回的元素 
        Q2.push(Q1.front());
        Q1.pop();
    }
    int res = Q1.front();
    Q1.pop();
    Q1 = Q2;//将备份的元素重新放回Q1 
    while(!Q2.empty()) {
      Q2.pop();
    }
    return res;
    }
    int top() {
      int res = Q1.back();
    return res;
    }
    bool empty() {
    return Q1.empty();
    }
};

思路优化

仔细考虑发现,我们用另一个队列是备份元素的作用,那么我们可以直接把元素(除了最后一个)放置到队列的末尾,最后弹出元素的顺序就和栈一样了.

参考代码2

class MyStack {
public:
  queue<int> Q1;
  queue<int> Q2;
    MyStack() {
    }
    void push(int x) {
      Q1.push(x);
    }
    int pop() {
      int size = Q1.size();
      size--;
      while(size--){// 弹出size-1个元素放置到Q1的末尾.. 
        Q1.push(Q1.front());
        Q1.pop();
    }
    int res = Q1.front();
    Q1.pop();
    return res;
    }
    int top() {
      int res = Q1.back();
    return res;
    }
    bool empty() {
    return Q1.empty();
    }
};

20. 有效的括号


给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。

左括号必须以正确的顺序闭合。


示例 1:

输入:s = "()"
输出:true


示例 2:

输入:s = "()[]{}"
输出:true


示例 3:

输入:s = "(]"
输出:false


示例 4:

输入:s = "([)]"
输出:false


示例 5:

输入:s = "{[]}"
输出:true


方法一

栈的基本使用

参考代码1


bool isValid(string s) {
  stack<char> tab;
  for(char ch : s){
    if(tab.empty()){
      tab.push(ch);
    }else{
      if((tab.top()=='('&&ch==')') ||(tab.top()=='{'&&ch=='}')|| (tab.top()=='['&&ch==']')){
        tab.pop();
      }else{
        tab.push(ch);
      }
    }
  }
  return s.empty();
}


方法二

字符串不匹配的三种情况:

  • 第一种情况,字符串里左方向的括号多余了 ,所以不匹配。


image.png

第二种情况,括号没有多余,但是 括号的类型没有匹配上

image.png

第三种情况,字符串里右方向的括号多余了,所以不匹配。

0c96ecc67fab4124b8c81ac7413bd026.png

算法步骤:


第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false


第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false


第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false


小技巧,在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了!

参考代码2

bool isValid(string s) {
        stack<int> 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(']');
            // 第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号 return false
            // 第二种情况:遍历字符串匹配的过程中,发现栈里没有我们要匹配的字符。所以return false
            else if (st.empty() || st.top() != s[i]) return false;
            else st.pop(); // st.top() 与 s[i]相等,栈弹出元素
        }
        // 第一种情况:此时我们已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false,否则就return true
        return st.empty();
    }


相关文章
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
57 6
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
52 4
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
118 2
|
25天前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
21 1
|
2月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
3月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
61 7
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
54 5
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 30. 包含min函数的栈
本文提供了实现一个包含min函数的栈的Python代码,确保min、push和pop操作的时间复杂度为O(1)。
28 4
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
Leetcode题目"剑指 Offer 21. 调整数组顺序使奇数位于偶数前面"的两种Python解决方案,一种是使用双端队列调整数组顺序,另一种是使用双指针法将奇数移到数组前半部分,偶数移到后半部分。
28 4