速通Hot100-Day07——栈

232.用栈实现队列

【分析】时间push/emptyO(1)pop/peekO(n),空间O(n)

时间复杂度:push 和 empty 为 O(1),pop 和 peek 为均摊 O(1)。对于每个元素,至多入栈和出栈各两次,故均摊复杂度为 O(1)。

空间复杂度:O(n)。其中 n 是操作总数。对于有 n 次 push 操作的情况,队列中会有 n 个元素,故空间复杂度为 O(n)。

【思想】栈与队列的特性:FILO、FIFO

用两个栈才能模拟队列的FIFO

java 复制代码
class MyQueue {

    private LinkedList<Integer> stOut;
    private LinkedList<Integer> stIn;

    public MyQueue() {
        stOut = new LinkedList<>();
        stIn = new LinkedList<>();
    }
    
    public void push(int x) {
        stIn.push(x);
    }
    
    public int pop() {
        transferIfEmpty();
        return stOut.pop();
    }
    
    public int peek() {
        transferIfEmpty();
        return stOut.peek();
    }
    
    public boolean empty() {
        return stIn.isEmpty() && stOut.isEmpty();
    }

    private void transferIfEmpty() {
        while(stOut.isEmpty()) {
            while(!stIn.isEmpty()) {
                stOut.push(stIn.pop());
            }
        }
    }
}

/**
 * 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();
 * boolean param_4 = obj.empty();
 */

225. 用队列实现栈

【分析】

时间:入栈操作 O(n),其余操作都是 O(1),其中 n 是栈内的元素个数。

  • 入栈操作需要将队列中的 n 个元素出队,并入队 n+1 个元素到队列,共有 2n+1 次操作,每次出队和入队操作的时间复杂度都是 O(1),因此入栈操作的时间复杂度是 O(n)。
  • 出栈操作对应将队列的前端元素出队,时间复杂度是 O(1)。
  • 获得栈顶元素操作对应获得队列的前端元素,时间复杂度是 O(1)。
  • 判断栈是否为空操作只需要判断队列是否为空,时间复杂度是 O(1)。

空间:O(n),其中 n 是栈内的元素个数。需要使用一个队列存储栈内的元素。

【思想】用一个队列就能模拟栈的FILO,队头队尾元素罢了

top查看栈顶元素,所以需要将最后一个元素还给qout,对比一下两段的代码

java 复制代码
public int pop() {
        while(qin.size() > 1) {
            qout.offer(qin.poll());
        }
        int res = qin.poll();



public int top() {
        while(qin.size() > 1) {
            qout.offer(qin.poll());
        }
        int res = qin.poll();
        qout.offer(res);
java 复制代码
class MyStack {

    LinkedList<Integer> qin;
    LinkedList<Integer> qout;

    public MyStack() {
        qin = new LinkedList<>();
        qout = new LinkedList<>();
    }
    
    public void push(int x) {
        qin.offer(x);
    }
    
    public int pop() {
        while(qin.size() > 1) {
            qout.offer(qin.poll());
        }
        int res = qin.poll();
        LinkedList<Integer> tmp = qin;
        qin = qout;
        qout = tmp;
        return res;
    }
    
    public int top() {
        while(qin.size() > 1) {
            qout.offer(qin.poll());
        }
        int res = qin.poll();
        qout.offer(res);

        LinkedList<Integer> tmp = qin;
        qin = qout;
        qout = tmp;
        return res;
    }
    
    public boolean empty() {
        return qin.isEmpty() && qout.isEmpty();
    }
}

/**
 * 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();
 * boolean param_4 = obj.empty();
 */

20. 有效的括号

  • 时间复杂度:O(n),其中 n 是 s 的长度。
  • 空间复杂度:O(n) 。

两个 return 语句可以互换位置,但是匹配的必须在最后

java 复制代码
if(tt == -1) return false; // 空了,但是还没遍历完
if(tt != -1 && st[tt] != c) return false; // 不匹配

if(tt != -1 && st[tt] == c) tt--; // 匹配往后退

出现错误的情况:匹配了回退tt 0 -> -1 触发 if(tt == -1) return false;明明匹配,还没遍历完,但是认为错了。举例如下:

java 复制代码
场景: 栈中有一个元素 ')',栈顶 tt=0,当前字符 c = ')'
第一个 if: tt != -1 && st[tt] == c → 条件成立,tt-- 变为 -1
第二个 if: tt != -1 && st[tt] != c → tt == -1,条件不成立
第三个 if: tt == -1 → 条件成立,返回 false ❌
结果: 明明匹配成功,却返回了 false,这是错误的!
java 复制代码
class Solution {
    public boolean isValid(String s) {
        char[] st = new char[10010];
        int tt = -1;

        for(int i = 0;i < s.length();i++) {
            char c = s.charAt(i);
            if(c == '(') {
                st[++tt] = ')';
            } else if(c == '[') {
                st[++tt] = ']';
            } else if(c == '{') {
                st[++tt] = '}';
            } else {
                if(tt == -1) return false; // 空了,但是还没遍历完
                if(tt != -1 && st[tt] != c) return false; // 不匹配
            
                if(tt != -1 && st[tt] == c) tt--; // 匹配往后退
                
            }  
        }
        return tt == -1;
    }
}
相关推荐
꧁细听勿语情꧂15 小时前
用队列实现栈、用栈实现队列,树、二叉树、满二叉树、完全二叉树,堆、向下向上调整算法、出堆入堆、堆排序
c语言·开发语言·数据结构·算法
周末也要写八哥15 小时前
什么是快速选择及案例分析
数据结构
碧海银沙音频科技研究院15 小时前
BES2800BP_nuttx编译环境搭建方法
人工智能·深度学习·算法
Felven15 小时前
B. Make Almost Equal With Mod
数据结构·算法
脆皮炸鸡75515 小时前
Linux~~基础IO
linux·运维·服务器·经验分享·算法·学习方法
踩坑记录15 小时前
leetcode hot100 416. 分割等和子集 medium 动态规划 01背包 DFS深度优先搜索
leetcode·深度优先·动态规划
colofullove15 小时前
文本分块策略与预处理
算法
三毛的二哥15 小时前
BEV:感知抖动问题及解决办法
人工智能·算法·计算机视觉
AI科技星15 小时前
宇宙终极几何:莫比乌斯光速螺旋统一理论-精细结构常数α本源结构
算法·机器学习·数学建模·数据挖掘·量子计算
数智化精益手记局15 小时前
拆解红牌作战的步骤:掌握红牌作战的步骤,解决现场管理难题
大数据·数据结构·人工智能·制造·精益工程