@@ -87,38 +87,60 @@ movieRentingSystem.search(2); // 返回 [0, 1] 。商店 0 和 1 有未借出
8787
8888<!-- solution:start -->
8989
90- ### 方法一
90+ ### 方法一:有序集合
91+
92+ 我们定义一个有序集合 $\textit{available}$,其中 $\textit{available}[ movie] $ 存储所有未借出的电影 $movie$ 的商店列表,列表中的元素为 $(\textit{price}, \textit{shop})$,并按照 $\textit{price}$ 升序排序,如果 $\textit{price}$ 相同,则按照 $\textit{shop}$ 升序排序。
93+
94+ 另外定义一个哈希表 $\textit{price\_ map}$,其中 $\textit{price\_ map}[ f(\textit{shop}, \textit{movie})] $ 存储商店 $\textit{shop}$ 中电影 $\textit{movie}$ 的租借价格。
95+
96+ 我们还定义一个有序集合 $\textit{rented}$,其中存储所有已借出的电影,元素为 $(\textit{price}, \textit{shop}, \textit{movie})$,并按照 $\textit{price}$ 升序排序,如果 $\textit{price}$ 相同,则按照 $\textit{shop}$ 升序排序,如果 $\textit{shop}$ 也相同,则按照 $\textit{movie}$ 升序排序。
97+
98+ 对于 $\text{MovieRentingSystem}(n, \text{entries})$ 操作,我们遍历 $\text{entries}$,将每个商店的电影信息加入到 $\textit{available}$ 和 $\textit{price\_ map}$ 中。时间复杂度为 $O(m \log m)$,其中 $m$ 是 $\text{entries}$ 的长度。
99+
100+ 对于 $\text{search}(\text{movie})$ 操作,我们返回 $\textit{available}[ \text{movie}] $ 中前 5 个商店的编号。时间复杂度为 $O(1)$。
101+
102+ 对于 $\text{rent}(\text{shop}, \text{movie})$ 操作,我们从 $\textit{available}[ \text{movie}] $ 中移除 $(\textit{price}, \textit{shop})$,并将 $(\textit{price}, \textit{shop}, \textit{movie})$ 加入到 $\textit{rented}$ 中。时间复杂度为 $O(\log m)$。
103+
104+ 对于 $\text{drop}(\text{shop}, \text{movie})$ 操作,我们从 $\textit{rented}$ 中移除 $(\textit{price}, \textit{shop}, \textit{movie})$,并将 $(\textit{price}, \textit{shop})$ 加入到 $\textit{available}[ \text{movie}] $ 中。时间复杂度为 $O(\log m)$。
105+
106+ 对于 $\text{report}()$ 操作,我们返回 $\textit{rented}$ 中前 5 个已借出电影的商店编号和电影编号。时间复杂度为 $O(1)$。
107+
108+ 空间复杂度为 $O(m)$。其中 $m$ 是 $\text{entries}$ 的长度。
91109
92110<!-- tabs:start -->
93111
94112#### Python3
95113
96114``` python
97115class MovieRentingSystem :
116+
98117 def __init__ (self , n : int , entries : List[List[int ]]):
99- self .unrented = collections.defaultdict(SortedList) # {movie: (price, shop)}
100- self .shopAndMovieToPrice = {} # {(shop, movie): price}
101- self .rented = SortedList() # (price, shop, movie)
118+ self .available = defaultdict(lambda : SortedList())
119+ self .price_map = {}
102120 for shop, movie, price in entries:
103- self .unrented[movie].add((price, shop))
104- self .shopAndMovieToPrice[(shop, movie)] = price
121+ self .available[movie].add((price, shop))
122+ self .price_map[self .f(shop, movie)] = price
123+ self .rented = SortedList()
105124
106125 def search (self , movie : int ) -> List[int ]:
107- return [shop for _, shop in self .unrented [movie][:5 ]]
126+ return [shop for _, shop in self .available [movie][:5 ]]
108127
109128 def rent (self , shop : int , movie : int ) -> None :
110- price = self .shopAndMovieToPrice[ (shop, movie)]
111- self .unrented [movie].remove((price, shop))
129+ price = self .price_map[ self .f (shop, movie)]
130+ self .available [movie].remove((price, shop))
112131 self .rented.add((price, shop, movie))
113132
114133 def drop (self , shop : int , movie : int ) -> None :
115- price = self .shopAndMovieToPrice[(shop, movie)]
116- self .unrented[movie].add((price, shop))
134+ price = self .price_map[self .f(shop, movie)]
117135 self .rented.remove((price, shop, movie))
136+ self .available[movie].add((price, shop))
118137
119138 def report (self ) -> List[List[int ]]:
120139 return [[shop, movie] for _, shop, movie in self .rented[:5 ]]
121140
141+ def f (self , shop : int , movie : int ) -> int :
142+ return shop << 30 | movie
143+
122144
123145# Your MovieRentingSystem object will be instantiated and called as such:
124146# obj = MovieRentingSystem(n, entries)
@@ -128,6 +150,268 @@ class MovieRentingSystem:
128150# param_4 = obj.report()
129151```
130152
153+ #### Java
154+
155+ ``` java
156+ class MovieRentingSystem {
157+ private Map<Integer , TreeSet<int[]> > available = new HashMap<> ();
158+ private Map<Long , Integer > priceMap = new HashMap<> ();
159+ private TreeSet<int[]> rented = new TreeSet<> ((a, b) - > {
160+ if (a[0 ] != b[0 ]) {
161+ return a[0 ] - b[0 ];
162+ }
163+ if (a[1 ] != b[1 ]) {
164+ return a[1 ] - b[1 ];
165+ }
166+ return a[2 ] - b[2 ];
167+ });
168+
169+ public MovieRentingSystem (int n , int [][] entries ) {
170+ for (int [] entry : entries) {
171+ int shop = entry[0 ], movie = entry[1 ], price = entry[2 ];
172+ available
173+ .computeIfAbsent(movie, k - > new TreeSet<> ((a, b) - > {
174+ if (a[0 ] != b[0 ]) {
175+ return a[0 ] - b[0 ];
176+ }
177+ return a[1 ] - b[1 ];
178+ }))
179+ .add(new int [] {price, shop});
180+ priceMap. put(f(shop, movie), price);
181+ }
182+ }
183+
184+ public List<Integer > search (int movie ) {
185+ List<Integer > res = new ArrayList<> ();
186+ if (! available. containsKey(movie)) {
187+ return res;
188+ }
189+ int cnt = 0 ;
190+ for (int [] item : available. get(movie)) {
191+ res. add(item[1 ]);
192+ if (++ cnt == 5 ) {
193+ break ;
194+ }
195+ }
196+ return res;
197+ }
198+
199+ public void rent (int shop , int movie ) {
200+ int price = priceMap. get(f(shop, movie));
201+ available. get(movie). remove(new int [] {price, shop});
202+ rented. add(new int [] {price, shop, movie});
203+ }
204+
205+ public void drop (int shop , int movie ) {
206+ int price = priceMap. get(f(shop, movie));
207+ rented. remove(new int [] {price, shop, movie});
208+ available. get(movie). add(new int [] {price, shop});
209+ }
210+
211+ public List<List<Integer > > report () {
212+ List<List<Integer > > res = new ArrayList<> ();
213+ int cnt = 0 ;
214+ for (int [] item : rented) {
215+ res. add(Arrays . asList(item[1 ], item[2 ]));
216+ if (++ cnt == 5 ) {
217+ break ;
218+ }
219+ }
220+ return res;
221+ }
222+
223+ private long f (int shop , int movie ) {
224+ return ((long ) shop << 30 ) | movie;
225+ }
226+ }
227+
228+ /**
229+ * Your MovieRentingSystem object will be instantiated and called as such:
230+ * MovieRentingSystem obj = new MovieRentingSystem(n, entries);
231+ * List<Integer> param_1 = obj.search(movie);
232+ * obj.rent(shop,movie);
233+ * obj.drop(shop,movie);
234+ * List<List<Integer>> param_4 = obj.report();
235+ */
236+ ```
237+
238+ #### C++
239+
240+ ``` cpp
241+ class MovieRentingSystem {
242+ private:
243+ unordered_map<int, set<pair<int, int>>> available; // movie -> {(price, shop)}
244+ unordered_map<long long, int> priceMap;
245+ set<tuple<int, int, int>> rented; // {(price, shop, movie)}
246+
247+ long long f(int shop, int movie) {
248+ return ((long long) shop << 30) | movie;
249+ }
250+
251+ public:
252+ MovieRentingSystem (int n, vector<vector<int >>& entries) {
253+ for (auto& e : entries) {
254+ int shop = e[ 0] , movie = e[ 1] , price = e[ 2] ;
255+ available[ movie] .insert({price, shop});
256+ priceMap[ f(shop, movie)] = price;
257+ }
258+ }
259+
260+ vector<int> search(int movie) {
261+ vector<int> res;
262+ if (!available.count(movie)) {
263+ return res;
264+ }
265+ int cnt = 0;
266+ for (auto& [price, shop] : available[movie]) {
267+ res.push_back(shop);
268+ if (++cnt == 5) {
269+ break;
270+ }
271+ }
272+ return res;
273+ }
274+
275+ void rent(int shop, int movie) {
276+ int price = priceMap[f(shop, movie)];
277+ available[movie].erase({price, shop});
278+ rented.insert({price, shop, movie});
279+ }
280+
281+ void drop(int shop, int movie) {
282+ int price = priceMap[f(shop, movie)];
283+ rented.erase({price, shop, movie});
284+ available[movie].insert({price, shop});
285+ }
286+
287+ vector<vector<int>> report() {
288+ vector<vector<int>> res;
289+ int cnt = 0;
290+ for (auto& [price, shop, movie] : rented) {
291+ res.push_back({shop, movie});
292+ if (++cnt == 5) {
293+ break;
294+ }
295+ }
296+ return res;
297+ }
298+ };
299+
300+ /**
301+ * Your MovieRentingSystem object will be instantiated and called as such:
302+ * MovieRentingSystem* obj = new MovieRentingSystem(n, entries);
303+ * vector<int > param_1 = obj->search(movie);
304+ * obj->rent(shop,movie);
305+ * obj->drop(shop,movie);
306+ * vector<vector<int >> param_4 = obj->report();
307+ * /
308+ ```
309+
310+ #### Go
311+
312+ ```go
313+ type MovieRentingSystem struct {
314+ available map[int]*treeset.Set // movie -> (price, shop)
315+ priceMap map[int64]int
316+ rented *treeset.Set // (price, shop, movie)
317+ }
318+
319+ func Constructor(n int, entries [][]int) MovieRentingSystem {
320+ // comparator for (price, shop)
321+ cmpAvail := func(a, b any) int {
322+ x := a.([2]int)
323+ y := b.([2]int)
324+ if x[0] != y[0] {
325+ return x[0] - y[0]
326+ }
327+ return x[1] - y[1]
328+ }
329+ // comparator for (price, shop, movie)
330+ cmpRented := func(a, b any) int {
331+ x := a.([3]int)
332+ y := b.([3]int)
333+ if x[0] != y[0] {
334+ return x[0] - y[0]
335+ }
336+ if x[1] != y[1] {
337+ return x[1] - y[1]
338+ }
339+ return x[2] - y[2]
340+ }
341+
342+ mrs := MovieRentingSystem{
343+ available: make(map[int]*treeset.Set),
344+ priceMap: make(map[int64]int),
345+ rented: treeset.NewWith(cmpRented),
346+ }
347+
348+ for _, e := range entries {
349+ shop, movie, price := e[0], e[1], e[2]
350+ if _, ok := mrs.available[movie]; !ok {
351+ mrs.available[movie] = treeset.NewWith(cmpAvail)
352+ }
353+ mrs.available[movie].Add([2]int{price, shop})
354+ mrs.priceMap[f(shop, movie)] = price
355+ }
356+
357+ return mrs
358+ }
359+
360+ func (this *MovieRentingSystem) Search(movie int) []int {
361+ res := []int{}
362+ if _, ok := this.available[movie]; !ok {
363+ return res
364+ }
365+ it := this.available[movie].Iterator()
366+ it.Begin()
367+ cnt := 0
368+ for it.Next() && cnt < 5 {
369+ pair := it.Value().([2]int)
370+ res = append(res, pair[1])
371+ cnt++
372+ }
373+ return res
374+ }
375+
376+ func (this *MovieRentingSystem) Rent(shop int, movie int) {
377+ price := this.priceMap[f(shop, movie)]
378+ this.available[movie].Remove([2]int{price, shop})
379+ this.rented.Add([3]int{price, shop, movie})
380+ }
381+
382+ func (this *MovieRentingSystem) Drop(shop int, movie int) {
383+ price := this.priceMap[f(shop, movie)]
384+ this.rented.Remove([3]int{price, shop, movie})
385+ this.available[movie].Add([2]int{price, shop})
386+ }
387+
388+ func (this *MovieRentingSystem) Report() [][]int {
389+ res := [][]int{}
390+ it := this.rented.Iterator()
391+ it.Begin()
392+ cnt := 0
393+ for it.Next() && cnt < 5 {
394+ t := it.Value().([3]int)
395+ res = append(res, []int{t[1], t[2]})
396+ cnt++
397+ }
398+ return res
399+ }
400+
401+ func f(shop, movie int) int64 {
402+ return (int64(shop) << 30) | int64(movie)
403+ }
404+
405+ /**
406+ * Your MovieRentingSystem object will be instantiated and called as such:
407+ * obj := Constructor(n, entries);
408+ * param_1 := obj.Search(movie);
409+ * obj.Rent(shop,movie);
410+ * obj.Drop(shop,movie);
411+ * param_4 := obj.Report();
412+ */
413+ ```
414+
131415<!-- tabs:end -->
132416
133417<!-- solution:end -->
0 commit comments