力扣1912——设计电影租借系统

你有一个电影租借公司和 n 个电影商店。你想要实现一个电影租借系统,它支持查询、预订和返还电影的操作。同时系统还能生成一份当前被借出电影的报告。

所有电影用二维整数数组 entries 表示,其中 entries[i] = [shopi, moviei, pricei] 表示商店 shopi 有一份电影 moviei 的拷贝,租借价格为 pricei 。每个商店有 至多一份 编号为 moviei 的电影拷贝。

系统需要支持以下操作:

  • Search:找到拥有指定电影且 未借出 的商店中 最便宜的 5 个 。商店需要按照 价格 升序排序,如果价格相同,则 shopi 较小 的商店排在前面。如果查询结果少于 5 个商店,则将它们全部返回。如果查询结果没有任何商店,则返回空列表。
  • Rent:从指定商店借出指定电影,题目保证指定电影在指定商店 未借出 。
  • Drop:在指定商店返还 之前已借出 的指定电影。
  • Report:返回 最便宜的 5 部已借出电影 (可能有重复的电影 ID),将结果用二维列表 res 返回,其中 res[j] = [shopj, moviej] 表示第 j 便宜的已借出电影是从商店 shopj 借出的电影 moviej 。res 中的电影需要按 价格 升序排序;如果价格相同,则 shopj 较小 的排在前面;如果仍然相同,则 moviej 较小 的排在前面。如果当前借出的电影小于 5 部,则将它们全部返回。如果当前没有借出电影,则返回一个空的列表。

请你实现 MovieRentingSystem 类:

  • MovieRentingSystem(int n, int[][] entries) 将 MovieRentingSystem 对象用 n 个商店和 entries 表示的电影列表初始化。
  • List<Integer> search(int movie) 如上所述,返回 未借出 指定 movie 的商店列表。
  • void rent(int shop, int movie) 从指定商店 shop 借出指定电影 movie 。
  • void drop(int shop, int movie) 在指定商店 shop 返还之前借出的电影 movie 。
  • List<List<Integer>> report() 如上所述,返回最便宜的 已借出 电影列表。

注意:测试数据保证 rent 操作中指定商店拥有 未借出 的指定电影,且 drop 操作指定的商店 之前已借出 指定电影。

 

示例 1:

输入:
["MovieRentingSystem", "search", "rent", "rent", "report", "drop", "search"]
[[3, [[0, 1, 5], [0, 2, 6], [0, 3, 7], [1, 1, 4], [1, 2, 7], [2, 1, 5]]], [1], [0, 1], [1, 2], [], [1, 2], [2]]
输出:
[null, [1, 0, 2], null, null, [[0, 1], [1, 2]], null, [0, 1]]

解释:
MovieRentingSystem movieRentingSystem = new MovieRentingSystem(3, [[0, 1, 5], [0, 2, 6], [0, 3, 7], [1, 1, 4], [1, 2, 7], [2, 1, 5]]);
movieRentingSystem.search(1); // 返回 [1, 0, 2] ,商店 1,0 和 2 有未借出的 ID 为 1 的电影。商店 1 最便宜,商店 0 和 2 价格相同,所以按商店编号排序。
movieRentingSystem.rent(0, 1); // 从商店 0 借出电影 1 。现在商店 0 未借出电影编号为 [2,3] 。
movieRentingSystem.rent(1, 2); // 从商店 1 借出电影 2 。现在商店 1 未借出的电影编号为 [1] 。
movieRentingSystem.report(); // 返回 [[0, 1], [1, 2]] 。商店 0 借出的电影 1 最便宜,然后是商店 1 借出的电影 2 。
movieRentingSystem.drop(1, 2); // 在商店 1 返还电影 2 。现在商店 1 未借出的电影编号为 [1,2] 。
movieRentingSystem.search(2); // 返回 [0, 1] 。商店 0 和 1 有未借出的 ID 为 2 的电影。商店 0 最便宜,然后是商店 1 。

 

提示:

  • 1 <= n <= 3 * 105
  • 1 <= entries.length <= 105
  • 0 <= shopi < n
  • 1 <= moviei, pricei <= 104
  • 每个商店 至多 有一份电影 moviei 的拷贝。
  • searchrentdrop 和 report 的调用 总共 不超过 105 次。

超时题解

这道题可以算作一道小模拟题。
创建了一个map<int,map<int,float,bool>> entries的变量,其中分别表示 shopi,moviei,price,isRent,其中false表示没有借出,true表示借出
search的时候是创建了一个优先队列,遍历所有影院,将所有该电影未租借的情况放入优先队列中,然后取出其中最小的5个,这样的复杂度很高,因为需要遍历所有
rent,drop的时候比较简单,只需要根据键值找到对应的value,修改isRent的值就可以了
report是在每次rent的时候就将租借信息放到一个优先队列中,因此只需要输出该优先队列中当前仍旧被租借且价格小的电影就可以
但是上面这样写,最后是超时,比较无奈

超时代码

点击查看代码
class MovieRentingSystem {
public:
    map<int,map<int,pair<float,bool>>> entries; //(shopi,(moviesi,[price,isRent]) false表示未借出

    struct cmpReport{
        bool operator()(pair<float,pair<int,int>>a, pair<float,pair<int,int>> b){
            if(a.first == b.first){
                if(a.second.first == b.second.first) return a.second.second > b.second.second;
                else return a.second.first > b.second.first;
            }
            else return a.first > b.first;
        }
    };
    

    //price shopi moviei
    priority_queue<pair<float,pair<int,int>>, vector<pair<float,pair<int,int>>>, cmpReport> qr; 


    


    int n;
    MovieRentingSystem(int n, vector<vector<int>>& entries) {
        this->n = n;
        for(int i = 0; i < entries.size(); i++){
            if(this->entries.count(entries[i][0]) == 0){
                map<int,pair<float,bool>> a;
                this->entries[entries[i][0]] = a;
            }
            pair<float,bool> b;
            b.first = entries[i][2]; //价格
            b.second = false;
            this->entries[entries[i][0]][entries[i][1]] = b;
        }
    }
    struct cmp{
        bool operator()(pair<int,int> a,pair<int,int> b){
            if(a.first == b.first) return a.second > b.second;
            else return a.first > b.first; 
        }
    };
    
    
    vector<int> search(int movie) {
        priority_queue<pair<float,int>,vector<pair<float,int>>,cmp> q;
        for(int i = 0 ; i < n; i++){
            if(entries[i].find(movie) != entries[i].end() && !entries[i][movie].second){
                pair<float,int> pa;
                pa.first = entries[i][movie].first;
                pa.second = i;
                q.push(pa);
            }
        }
        vector<int> ans;
        while(!q.empty()){
            ans.push_back(q.top().second);
            q.pop();
            if(ans.size() >= 5 ) break;
        }
        return ans;
    }
    
    void rent(int shop, int movie) {
        entries[shop][movie].second = true;
        pair<float,pair<int,int>> a;
        a.first = entries[shop][movie].first;
        a.second.first = shop;
        a.second.second = movie;
        qr.push(a);
    }
    
    void drop(int shop, int movie) {
        //if(entries[shop][movie].second == true){
            entries[shop][movie].second = false;
       // }
    }
    
    vector<vector<int>> report() {
        vector<vector<int>> ans;
        pair<float,pair<int,int>> b[5];
        while(!qr.empty()){
            pair<float,pair<int,int>> a = qr.top();
            qr.pop();
            if(entries[a.second.first][a.second.second].second == true){
                int plag = false; // 计算是否和之前找到的相同,如果相同则不要
                //因为可能会出现借了一次,还了,又接了一次,又还了,所以此时qr可能会存在两个相同的
                for(int i = 0; i < ans.size(); i++){
                    if(ans[i][0] == a.second.first && ans[i][1] == a.second.second){
                        plag = true;
                        break;
                    }
                }
                if(!plag){
                    vector<int> temp;
                    temp.push_back(a.second.first);
                    temp.push_back(a.second.second);
                    b[ans.size()] = a;
                    ans.push_back(temp);
                }
                
            }
            if(ans.size() >= 5) break;
        }

        for(int i = 0; i < ans.size(); i++){
            qr.push(b[i]);
        }
        return ans;

    }
};

/**
 * Your MovieRentingSystem object will be instantiated and called as such:
 * MovieRentingSystem* obj = new MovieRentingSystem(n, entries);
 * vector<int> param_1 = obj->search(movie);
 * obj->rent(shop,movie);
 * obj->drop(shop,movie);
 * vector<vector<int>> param_4 = obj->report();
 */

AC题解

看了网上的题解,才发现原先set是可以进行有序输出的
set<pair<int,int>> mv[10000+5] mv[i]表示电影i,则该set存储的是所有的<price,shop>
map<pair<int,int>,int> pr key是<shop,movie> value是price
set<pair<int,pair<int,int>>> rt <price,<shop,movie>>

AC代码

点击查看代码
class MovieRentingSystem {
public:
    int n ;
    //完成search操作,也就是需要movie为key或者index,这样就可以快速找到所有的含有该电影的信息
    //又因为需要输出价格最小的五个,因此需要使用有序的
    set<pair<int,int>> mv[10000+5]; //set可以满足有序  <price,shop>
    map<pair<int,int>,int> pr; // (shop,movie) -> price
    set<pair<int,pair<int,int>>> rt; // price,shop,movie

    MovieRentingSystem(int n, vector<vector<int>>& entries) {
        this->n = n;

        for(int i = 0; i < entries.size(); i++){
            int shop = entries[i][0];
            int movie = entries[i][1];
            int price = entries[i][2];
            mv[movie].insert(make_pair(price,shop));
            pr[make_pair(shop,movie)] = price;
        }
    }

    
    vector<int> search(int movie) {
        vector<int> ans;
        for(auto it = mv[movie].begin(); it != mv[movie].end(); it++){
            ans.push_back(it->second);
            if(ans.size() >= 5) break;
        }
        return ans;
    }
    
    void rent(int shop, int movie) {
        int price = pr[make_pair(shop,movie)];
        mv[movie].erase(make_pair(price,shop));
        rt.insert(make_pair(price,make_pair(shop,movie)));
    }
    
    void drop(int shop, int movie) {
        int price = pr[make_pair(shop,movie)];
        mv[movie].insert(make_pair(price,shop));
        rt.erase(make_pair(price,make_pair(shop,movie)));
    }
    
    vector<vector<int>> report() {
        vector<vector<int>> ans;
        for(auto it = rt.begin(); it != rt.end(); it++){
            vector<int> temp;
            temp.push_back(it->second.first);
            temp.push_back(it->second.second);
            ans.push_back(temp);
            if(ans.size() >= 5) break;
        }
        return ans;
    }
};

/**
 * Your MovieRentingSystem object will be instantiated and called as such:
 * MovieRentingSystem* obj = new MovieRentingSystem(n, entries);
 * vector<int> param_1 = obj->search(movie);
 * obj->rent(shop,movie);
 * obj->drop(shop,movie);
 * vector<vector<int>> param_4 = obj->report();
 */
posted @ 2022-09-23 21:08  白菜茄子  阅读(43)  评论(0编辑  收藏  举报