当前位置: 首页 > article >正文

力扣(LeetCode)1172. 餐盘栈(C++)

优先队列

解题思路:根据题意模拟。用数组存储无限数量的栈。重在实现 p u s h push push p o p pop pop 操作。

  1. 对于 p u s h push push 操作,需要知道当前从左往右第一个空栈的下标。分两类讨论:
    ①所有栈都是满的,那么我们创建一个新栈,新栈存 p u s h push push 进来的值,再将新栈加入数组尾部。
    ②已存在的某些栈未满,那么从左往右遍历数组,找到第一个未满的栈,第一个未满的栈存 p u s h push push 进来的值。

这样一来,我们发现每个 p u s h push push 的操作②的最坏平均时间复杂度 O ( n ) O(n) O(n) ,一共 n n n p u s h push push ,总体时间复杂度 O ( n 2 ) O(n^2) O(n2),题目给出 p u s h push push 操作最多调用 2 × 1 0 5 2 \times 10 ^ 5 2×105 次,时间 O ( n 2 ) O(n^2) O(n2) 必然超时。

操作②既然是遍历,有一个直观的优化方法:用优先队列,小根堆存储未满栈的下标。这样以来,维护未满的栈的时间复杂度就是 O ( l o g n ) O(logn) O(logn),每次维护完毕,堆顶就是最小下标。总体时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn),可以接受。

  1. 对于 p o p pop pop 操作,它等价于 p o p A t S t a c k popAtStack popAtStack 操作,将参数 i n d e x index index 设为数组最后位置。

  2. 对于 p o p A t S t a c k popAtStack popAtStack 操作,简单模拟即可。

提示:对于优先队列的维护,请思考边界。也可以看代码注释。

class DinnerPlates {
public:
    int capacity;
    vector<stack<int>> S;
    priority_queue<int, vector<int>, greater<int>> pq;  // 维护未满栈的下标
    DinnerPlates(int capacity) {
        this->capacity = capacity;
    }
    
    void push(int val) {
        if (pq.size() && pq.top() >= S.size()) {  // 清空越界下标
            pq = priority_queue<int, vector<int>, greater<int>>();
        }
        // while (pq.size() && pq.top() >= S.size()) pq.pop();  // 清空越界下标
        if (pq.empty()) {  // 插入新栈
            stack<int> ts;
            ts.push(val);
            if (capacity > 1) pq.push(S.size());
            S.push_back(ts);
        } else {  // 插入第一个未满栈
            int pos = pq.top();
            S[pos].push(val);
            if (S[pos].size() >= capacity) {  // 插入后,栈满
                pq.pop();  // 下标弹栈
            }
        }
    }
    
    int pop() {
        return popAtStack(S.size() - 1);
    }
    
    int popAtStack(int index) {
        if (index >= S.size() || S[index].empty()) {
            return -1;
        } else {
            int ans = S[index].top();
            S[index].pop();
            if (S[index].size() == capacity - 1) pq.push(index);
            while (S.size() && S.back().empty()) S.pop_back();
            return ans;
        }
    }
};

时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn) : 一共 n n n 次操作,每个操作的时间复杂度 O ( l o g n ) O(logn) O(logn) ,时间瓶颈在于维护堆。总体时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
空间复杂度 O ( n ) O(n) O(n) : 优先队列、栈的最坏空间复杂度 O ( n ) O(n) O(n)

AC

ac

致语

  • 理解思路很重要
  • 读者有问题请留言,清墨看到就会回复的。

http://www.kler.cn/news/17142.html

相关文章:

  • 电脑中病毒了怎么修复,计算机Windows系统预防faust勒索病毒方法
  • RUST 每日一省:泛型约束——trait
  • Java面试题JVM JDK 和 JRE
  • 9:00进去,9:05就出来了,这问的也太···
  • 麻雀键值数据库开发日志
  • Linux常用的压缩、解压缩以及scp远程传输命令的使用
  • Android中Paint字体的灵活使用
  • 如何将 Elasticsearch 和时间序列数据流用于可观察性指标 - 8.7
  • 宏观经济笔记--CPI和PPI
  • 使用rt thread studio新建一个rt thread工程的详细操作说明(以stm32F411CEU6)为例
  • Python---多线程编程、基于Socket完成服务端程序开发、基于Socket完成客户端程序开发
  • SpringMVC详细介绍和@RequestMapping详细使用说明
  • 预制菜,巨头们的新赛场
  • python3 强制使用任意父级相对导入,越过python相对导入限制,拒绝 ImportError
  • 操作系统——设备管理
  • kafka的安装与使用
  • 关于低代码开发平台的一些想法
  • 【Frame.h】
  • 手写堆priority_queue优先队列
  • 题目:16版.学生-成绩关联实体
  • Centos7快速安装Kibana并连接ES使用
  • 结合SSE实现实时位置展示与轨迹展示
  • 区块链系统探索之路:基于椭圆曲线的私钥与公钥生成
  • FPGA/Verilog HDL/AC620零基础入门学习——8*8同步FIFO实验
  • spring-模型数据和视图---视图解析器的说明以及大量代码演示
  • AUTOSAR知识点Com(十三):ComM内容分析
  • 后端程序员的前端必备【Vue】- 01 Vue入门
  • 计算机Z20-第7-8周作业
  • 17. Pod 自动管理——DeamonSet 和 Job
  • JDK8 中Arrays.sort() 排序方法解读