鱼C论坛

 找回密码
 立即注册
查看: 821|回复: 1

队列操作时间复杂度问题

[复制链接]
发表于 2024-1-18 16:57:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
问题如下:

给定一个初始状态为空的序列,它将按顺序执行Q个操作
操作分为以下三种:
1 将a插入队列的末尾
2:查询队首元素,并将其删除。数据保证此时A非空
3:将队列升序排排序
输入描述:
第一行一个正整数Q(1 < Q < 2 x 10^5,表示操作数接下来Q行,每行表示一个操作
输出描述:
对于每个操作,输出一行一个正整数表示本次询问的答案。

求问大佬如何改进时间复杂度?

#include <iostream>
#include <vector>
#include <algorithm>
typedef long long ll;

using namespace std;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    vector<ll> queue, dp;
    ll num, cnum = 0;
    ll temp,ans;
    bool bol=0,judge;
    cin >> num;

    for (ll i = 0; i < num; i++) {
        cin >> temp;

        if (temp == 1) {
            cin >> temp;
            queue.push_back(temp);
        }
        else if (temp == 2) {
            dp.push_back(queue.front());
            queue.erase(queue.begin());
            cnum += 1;
        }
        else if (temp == 3&&ans!=3) {
            sort(queue.begin(), queue.end());
        }
        ans = temp;
    }

    for (ll i = 0; i < cnum; i++) {
        cout << dp[i] << '\n';
    }

    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-1-18 16:58:55 | 显示全部楼层
这道题的关键是如何改进时间复杂度。目前的代码中,每次执行操作2时,都需要遍历整个队列来查询并删除队首元素,导致时间复杂度为O(n),其中n表示当前队列的长度。而操作3中,每次都需要对整个队列进行排序,时间复杂度也是O(nlogn)。

我们可以使用两个队列来优化这个问题。一个队列用来保存原始的输入数据,另一个队列用来保存当前队列的有序状态。具体做法如下:

1. 当执行插入操作时,将元素插入到原始队列的末尾,并同时插入到有序队列的合适位置。
2. 当执行查询并删除队首元素操作时,直接从有序队列的队首获取即可,并从原始队列中删除。
3. 当执行排序操作时,不需要对整个队列进行排序,只需重新确定有序队列的元素顺序即可。

以下是改进后的代码:
#include <iostream>
#include <vector>
#include <algorithm>

typedef long long ll;

using namespace std;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    vector<int> originalQueue, sortedQueue;
    ll num, cnum = 0;
    ll temp, ans;
    bool bol = 0, judge;
    cin >> num;

    for (ll i = 0; i < num; i++) {
        cin >> temp;

        if (temp == 1) {
            cin >> temp;
            originalQueue.push_back(temp);
            
            // 将新插入的元素插入到有序队列的合适位置
            auto it = lower_bound(sortedQueue.begin(), sortedQueue.end(), temp);
            sortedQueue.insert(it, temp);
            
        } else if (temp == 2) {
            cout << sortedQueue.front() << endl;
            
            // 从原始队列和有序队列中删除队首元素
            originalQueue.erase(originalQueue.begin());
            sortedQueue.erase(sortedQueue.begin());
            
            cnum += 1;
            
        } else if (temp == 3 && ans != 3) {
            // 无需对整个队列进行排序,只需重新确定有序队列的元素顺序
            sort(sortedQueue.begin(), sortedQueue.end());
        }
        ans = temp;
    }

    for (ll i = 0; i < cnum; i++) {
        cout << sortedQueue[i] << endl;
    }
    
    return 0;
}
这样做的话,每次执行操作2时只需要从有序队列的队首取出元素即可,时间复杂度为O(1),而操作3的时间复杂度也为O(nlogn),但是由于操作3不是连续执行的,所以整体的时间复杂度会得到极大的优化。

希望可以帮助到你!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 23:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表