首页 > 其他分享 >力扣1912——设计电影租借系统

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

时间:2022-09-23 21:24:12浏览次数:86  
标签:租借 shop 借出 int movie 力扣 second entries 1912

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();
 */

标签:租借,shop,借出,int,movie,力扣,second,entries,1912
From: https://www.cnblogs.com/sunjianzhao/p/16724228.html

相关文章

  • 力扣_剑指Offer_个人解题资料
    day01剑指Offer09.用两个栈实现队列:题目描述:用两个栈实现一个队列。队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入整数和在队列......
  • 力扣21(java&python)-合并两个有序链表(简单)
    题目:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。  示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1......
  • 力扣445(java&python)-两数相加Ⅱ(中等)
    题目:给你两个非空链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。你可以假设除了数字0之外......
  • 力扣2(java&python)-两数相加(中等)
    题目:给你两个 非空的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表......
  • 力扣92(java&python)-反转链表Ⅱ(中等)
    题目:给你单链表的头指针head和两个整数 left和right,其中 left<=right。请你反转从位置left到位置right的链表节点,返回反转后的链表。示例1:输入:head=......
  • 力扣dp
    97.classSolution{public:boolisInterleave(strings1,strings2,strings3){intlen1=s1.length(),len2=s2.length(),len3=s3.length();......
  • 2022/9/18——zTao.力扣杂记
    剪枝与回溯对于需要求出各种满足题目要求的组合类型的题目。往往需要用到剪枝策略。例如LeetCode44求组和总数、22括号生成、473火柴拼正方形、77组合、216组合总和3、13......
  • 力扣206(java&python)-反转链表(简单)
    题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。示例1:输入:head=[1,2,3,4,5]输出:[5,4,3,2,1]示例2:输入:head=[1,2]输出:[2,1]示例3:输入:head=......
  • 力扣591(java)-标签验证器(困难)
    题目:给定一个表示代码片段的字符串,你需要实现一个验证器来解析这段代码,并返回它是否合法。合法的代码片段需要遵守以下的所有规则:代码必须被合法的闭合标签包围。否则,代......
  • 力扣636(java)-函数的独占时间(中等)
    题目:有一个单线程CPU正在运行一个含有n道函数的程序。每道函数都有一个位于 0和n-1之间的唯一标识符。函数调用存储在一个调用栈上:当一个函数调用开始时,它......