Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 246946f

Browse files
feat: add solutions to lc problem: No.1912 (doocs#4735)
No.1912.Design Movie Rental System
1 parent 5944c37 commit 246946f

File tree

6 files changed

+851
-32
lines changed

6 files changed

+851
-32
lines changed

‎solution/1900-1999/1912.Design Movie Rental System/README.md‎

Lines changed: 295 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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
97115
class 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

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /