From cb0c435cc23e8887aa1cf8d36f9794e8ffdafe92 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Fri, 1 Sep 2023 14:36:23 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.1847 No.1847.Closest Room --- .../1800-1899/1847.Closest Room/README.md | 174 ++++++++++++++++++ .../1800-1899/1847.Closest Room/README_EN.md | 166 ++++++++++++++++- .../1800-1899/1847.Closest Room/Solution.cpp | 42 +++++ .../1800-1899/1847.Closest Room/Solution.go | 48 +++++ .../1800-1899/1847.Closest Room/Solution.java | 40 ++++ .../1800-1899/1847.Closest Room/Solution.py | 26 +++ 6 files changed, 495 insertions(+), 1 deletion(-) create mode 100644 solution/1800-1899/1847.Closest Room/Solution.cpp create mode 100644 solution/1800-1899/1847.Closest Room/Solution.go create mode 100644 solution/1800-1899/1847.Closest Room/Solution.java create mode 100644 solution/1800-1899/1847.Closest Room/Solution.py diff --git a/solution/1800-1899/1847.Closest Room/README.md b/solution/1800-1899/1847.Closest Room/README.md index fa04ec90a6a93..686244faf10c9 100644 --- a/solution/1800-1899/1847.Closest Room/README.md +++ b/solution/1800-1899/1847.Closest Room/README.md @@ -58,6 +58,16 @@ +**方法一:离线查询 + 有序集合 + 二分查找** + +我们注意到,查询的顺序并不影响答案,而且题目中涉及到房间面积的大小关系,因此,我们可以将查询按照最小面积从小到大排序,这样我们就可以从小到大依次处理每个查询。另外,我们也将房间按照面积从小到大排序。 + +接下来,我们创建一个有序列表,将所有房间的编号加入有序列表中。 + +然后,我们从小到大依次处理每个查询。对于每个查询,我们首先将所有面积小于等于当前查询的最小面积的房间从有序列表中移除。然后,我们在剩余的房间中,使用二分查找找到最接近当前查询的房间编号。如果不存在这样的房间,那么我们就返回 $-1$。 + +时间复杂度 $O(n \times \log n + k \times \log k)$,空间复杂度 $O(n + k)$。其中 $n$ 和 $k$ 分别是房间数和查询数。 + ### **Python3** @@ -65,7 +75,32 @@ ```python +from sortedcontainers import SortedList + +class Solution: + def closestRoom( + self, rooms: List[List[int]], queries: List[List[int]] + ) -> List[int]: + rooms.sort(key=lambda x: x[1]) + k = len(queries) + idx = sorted(range(k), key=lambda i: queries[i][1]) + ans = [-1] * k + i, n = 0, len(rooms) + sl = SortedList(x[0] for x in rooms) + for j in idx: + prefer, minSize = queries[j] + while i < n and rooms[i][1] < minSize: + sl.remove(rooms[i][0]) + i += 1 + if i == n: + break + p = sl.bisect_left(prefer) + if p < len(sl): + ans[j] = sl[p] + if p and (ans[j] == -1 or ans[j] - prefer >= prefer - sl[p - 1]): + ans[j] = sl[p - 1] + return ans ``` ### **Java** @@ -73,7 +108,146 @@ ```java +class Solution { + public int[] closestRoom(int[][] rooms, int[][] queries) { + int n = rooms.length; + int k = queries.length; + Arrays.sort(rooms, (a, b) -> a[1] - b[1]); + Integer[] idx = new Integer[k]; + for (int i = 0; i < k; i++) { + idx[i] = i; + } + Arrays.sort(idx, (i, j) -> queries[i][1] - queries[j][1]); + int i = 0; + TreeMap tm = new TreeMap<>(); + for (int[] room : rooms) { + tm.merge(room[0], 1, Integer::sum); + } + int[] ans = new int[k]; + Arrays.fill(ans, -1); + for (int j : idx) { + int prefer = queries[j][0], minSize = queries[j][1]; + while (i < n && rooms[i][1] < minSize) { + if (tm.merge(rooms[i][0], -1, Integer::sum) == 0) { + tm.remove(rooms[i][0]); + } + ++i; + } + if (i == n) { + break; + } + Integer p = tm.ceilingKey(prefer); + if (p != null) { + ans[j] = p; + } + p = tm.floorKey(prefer); + if (p != null && (ans[j] == -1 || ans[j] - prefer >= prefer - p)) { + ans[j] = p; + } + } + return ans; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + vector closestRoom(vector>& rooms, vector>& queries) { + int n = rooms.size(); + int k = queries.size(); + sort(rooms.begin(), rooms.end(), [](const vector& a, const vector& b) { + return a[1] < b[1]; + }); + vector idx(k); + iota(idx.begin(), idx.end(), 0); + sort(idx.begin(), idx.end(), [&](int i, int j) { + return queries[i][1] < queries[j][1]; + }); + vector ans(k, -1); + int i = 0; + multiset s; + for (auto& room : rooms) { + s.insert(room[0]); + } + for (int j : idx) { + int prefer = queries[j][0], minSize = queries[j][1]; + while (i < n && rooms[i][1] < minSize) { + s.erase(s.find(rooms[i][0])); + ++i; + } + if (i == n) { + break; + } + auto it = s.lower_bound(prefer); + if (it != s.end()) { + ans[j] = *it; + } + if (it != s.begin()) { + --it; + if (ans[j] == -1 || abs(*it - prefer) <= abs(ans[j] - prefer)) { + ans[j] = *it; + } + } + } + return ans; + } +}; +``` + +### **Go** + +```go +func closestRoom(rooms [][]int, queries [][]int) []int { + n, k := len(rooms), len(queries) + sort.Slice(rooms, func(i, j int) bool { return rooms[i][1] < rooms[j][1] }) + idx := make([]int, k) + ans := make([]int, k) + for i := range idx { + idx[i] = i + ans[i] = -1 + } + sort.Slice(idx, func(i, j int) bool { return queries[idx[i]][1] < queries[idx[j]][1] }) + rbt := redblacktree.NewWithIntComparator() + merge := func(rbt *redblacktree.Tree, key, value int) { + if v, ok := rbt.Get(key); ok { + nxt := v.(int) + value + if nxt == 0 { + rbt.Remove(key) + } else { + rbt.Put(key, nxt) + } + } else { + rbt.Put(key, value) + } + } + for _, room := range rooms { + merge(rbt, room[0], 1) + } + i := 0 + for _, j := range idx { + prefer, minSize := queries[j][0], queries[j][1] + for i < n && rooms[i][1] < minSize { + merge(rbt, rooms[i][0], -1) + i++ + } + if i == n { + break + } + c, _ := rbt.Ceiling(prefer) + f, _ := rbt.Floor(prefer) + if c != nil { + ans[j] = c.Key.(int) + } + if f != nil && (ans[j] == -1 || ans[j]-prefer >= prefer-f.Key.(int)) { + ans[j] = f.Key.(int) + } + } + return ans +} ``` ### **...** diff --git a/solution/1800-1899/1847.Closest Room/README_EN.md b/solution/1800-1899/1847.Closest Room/README_EN.md index 1f5a32ab4e049..ae8f2c1236270 100644 --- a/solution/1800-1899/1847.Closest Room/README_EN.md +++ b/solution/1800-1899/1847.Closest Room/README_EN.md @@ -57,13 +57,177 @@ Query = [2,5]: Room number 3 is the only room with a size of at least 5. The ans ### **Python3** ```python - +from sortedcontainers import SortedList + + +class Solution: + def closestRoom( + self, rooms: List[List[int]], queries: List[List[int]] + ) -> List[int]: + rooms.sort(key=lambda x: x[1]) + k = len(queries) + idx = sorted(range(k), key=lambda i: queries[i][1]) + ans = [-1] * k + i, n = 0, len(rooms) + sl = SortedList(x[0] for x in rooms) + for j in idx: + prefer, minSize = queries[j] + while i < n and rooms[i][1] < minSize: + sl.remove(rooms[i][0]) + i += 1 + if i == n: + break + p = sl.bisect_left(prefer) + if p < len(sl): + ans[j] = sl[p] + if p and (ans[j] == -1 or ans[j] - prefer >= prefer - sl[p - 1]): + ans[j] = sl[p - 1] + return ans ``` ### **Java** ```java +class Solution { + public int[] closestRoom(int[][] rooms, int[][] queries) { + int n = rooms.length; + int k = queries.length; + Arrays.sort(rooms, (a, b) -> a[1] - b[1]); + Integer[] idx = new Integer[k]; + for (int i = 0; i < k; i++) { + idx[i] = i; + } + Arrays.sort(idx, (i, j) -> queries[i][1] - queries[j][1]); + int i = 0; + TreeMap tm = new TreeMap<>(); + for (int[] room : rooms) { + tm.merge(room[0], 1, Integer::sum); + } + int[] ans = new int[k]; + Arrays.fill(ans, -1); + for (int j : idx) { + int prefer = queries[j][0], minSize = queries[j][1]; + while (i < n && rooms[i][1] < minSize) { + if (tm.merge(rooms[i][0], -1, Integer::sum) == 0) { + tm.remove(rooms[i][0]); + } + ++i; + } + if (i == n) { + break; + } + Integer p = tm.ceilingKey(prefer); + if (p != null) { + ans[j] = p; + } + p = tm.floorKey(prefer); + if (p != null && (ans[j] == -1 || ans[j] - prefer >= prefer - p)) { + ans[j] = p; + } + } + return ans; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + vector closestRoom(vector>& rooms, vector>& queries) { + int n = rooms.size(); + int k = queries.size(); + sort(rooms.begin(), rooms.end(), [](const vector& a, const vector& b) { + return a[1] < b[1]; + }); + vector idx(k); + iota(idx.begin(), idx.end(), 0); + sort(idx.begin(), idx.end(), [&](int i, int j) { + return queries[i][1] < queries[j][1]; + }); + vector ans(k, -1); + int i = 0; + multiset s; + for (auto& room : rooms) { + s.insert(room[0]); + } + for (int j : idx) { + int prefer = queries[j][0], minSize = queries[j][1]; + while (i < n && rooms[i][1] < minSize) { + s.erase(s.find(rooms[i][0])); + ++i; + } + if (i == n) { + break; + } + auto it = s.lower_bound(prefer); + if (it != s.end()) { + ans[j] = *it; + } + if (it != s.begin()) { + --it; + if (ans[j] == -1 || abs(*it - prefer) <= abs(ans[j] - prefer)) { + ans[j] = *it; + } + } + } + return ans; + } +}; +``` +### **Go** + +```go +func closestRoom(rooms [][]int, queries [][]int) []int { + n, k := len(rooms), len(queries) + sort.Slice(rooms, func(i, j int) bool { return rooms[i][1] < rooms[j][1] }) + idx := make([]int, k) + ans := make([]int, k) + for i := range idx { + idx[i] = i + ans[i] = -1 + } + sort.Slice(idx, func(i, j int) bool { return queries[idx[i]][1] < queries[idx[j]][1] }) + rbt := redblacktree.NewWithIntComparator() + merge := func(rbt *redblacktree.Tree, key, value int) { + if v, ok := rbt.Get(key); ok { + nxt := v.(int) + value + if nxt == 0 { + rbt.Remove(key) + } else { + rbt.Put(key, nxt) + } + } else { + rbt.Put(key, value) + } + } + for _, room := range rooms { + merge(rbt, room[0], 1) + } + i := 0 + + for _, j := range idx { + prefer, minSize := queries[j][0], queries[j][1] + for i < n && rooms[i][1] < minSize { + merge(rbt, rooms[i][0], -1) + i++ + } + if i == n { + break + } + c, _ := rbt.Ceiling(prefer) + f, _ := rbt.Floor(prefer) + if c != nil { + ans[j] = c.Key.(int) + } + if f != nil && (ans[j] == -1 || ans[j]-prefer >= prefer-f.Key.(int)) { + ans[j] = f.Key.(int) + } + } + return ans +} ``` ### **...** diff --git a/solution/1800-1899/1847.Closest Room/Solution.cpp b/solution/1800-1899/1847.Closest Room/Solution.cpp new file mode 100644 index 0000000000000..de082720e8687 --- /dev/null +++ b/solution/1800-1899/1847.Closest Room/Solution.cpp @@ -0,0 +1,42 @@ +class Solution { +public: + vector closestRoom(vector>& rooms, vector>& queries) { + int n = rooms.size(); + int k = queries.size(); + sort(rooms.begin(), rooms.end(), [](const vector& a, const vector& b) { + return a[1] < b[1]; + }); + vector idx(k); + iota(idx.begin(), idx.end(), 0); + sort(idx.begin(), idx.end(), [&](int i, int j) { + return queries[i][1] < queries[j][1]; + }); + vector ans(k, -1); + int i = 0; + multiset s; + for (auto& room : rooms) { + s.insert(room[0]); + } + for (int j : idx) { + int prefer = queries[j][0], minSize = queries[j][1]; + while (i < n && rooms[i][1] < minSize) { + s.erase(s.find(rooms[i][0])); + ++i; + } + if (i == n) { + break; + } + auto it = s.lower_bound(prefer); + if (it != s.end()) { + ans[j] = *it; + } + if (it != s.begin()) { + --it; + if (ans[j] == -1 || abs(*it - prefer) <= abs(ans[j] - prefer)) { + ans[j] = *it; + } + } + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/1800-1899/1847.Closest Room/Solution.go b/solution/1800-1899/1847.Closest Room/Solution.go new file mode 100644 index 0000000000000..704918b40ff45 --- /dev/null +++ b/solution/1800-1899/1847.Closest Room/Solution.go @@ -0,0 +1,48 @@ +func closestRoom(rooms [][]int, queries [][]int) []int { + n, k := len(rooms), len(queries) + sort.Slice(rooms, func(i, j int) bool { return rooms[i][1] < rooms[j][1] }) + idx := make([]int, k) + ans := make([]int, k) + for i := range idx { + idx[i] = i + ans[i] = -1 + } + sort.Slice(idx, func(i, j int) bool { return queries[idx[i]][1] < queries[idx[j]][1] }) + rbt := redblacktree.NewWithIntComparator() + merge := func(rbt *redblacktree.Tree, key, value int) { + if v, ok := rbt.Get(key); ok { + nxt := v.(int) + value + if nxt == 0 { + rbt.Remove(key) + } else { + rbt.Put(key, nxt) + } + } else { + rbt.Put(key, value) + } + } + for _, room := range rooms { + merge(rbt, room[0], 1) + } + i := 0 + + for _, j := range idx { + prefer, minSize := queries[j][0], queries[j][1] + for i < n && rooms[i][1] < minSize { + merge(rbt, rooms[i][0], -1) + i++ + } + if i == n { + break + } + c, _ := rbt.Ceiling(prefer) + f, _ := rbt.Floor(prefer) + if c != nil { + ans[j] = c.Key.(int) + } + if f != nil && (ans[j] == -1 || ans[j]-prefer >= prefer-f.Key.(int)) { + ans[j] = f.Key.(int) + } + } + return ans +} \ No newline at end of file diff --git a/solution/1800-1899/1847.Closest Room/Solution.java b/solution/1800-1899/1847.Closest Room/Solution.java new file mode 100644 index 0000000000000..c647e70b3cf90 --- /dev/null +++ b/solution/1800-1899/1847.Closest Room/Solution.java @@ -0,0 +1,40 @@ +class Solution { + public int[] closestRoom(int[][] rooms, int[][] queries) { + int n = rooms.length; + int k = queries.length; + Arrays.sort(rooms, (a, b) -> a[1] - b[1]); + Integer[] idx = new Integer[k]; + for (int i = 0; i < k; i++) { + idx[i] = i; + } + Arrays.sort(idx, (i, j) -> queries[i][1] - queries[j][1]); + int i = 0; + TreeMap tm = new TreeMap<>(); + for (int[] room : rooms) { + tm.merge(room[0], 1, Integer::sum); + } + int[] ans = new int[k]; + Arrays.fill(ans, -1); + for (int j : idx) { + int prefer = queries[j][0], minSize = queries[j][1]; + while (i < n && rooms[i][1] < minSize) { + if (tm.merge(rooms[i][0], -1, Integer::sum) == 0) { + tm.remove(rooms[i][0]); + } + ++i; + } + if (i == n) { + break; + } + Integer p = tm.ceilingKey(prefer); + if (p != null) { + ans[j] = p; + } + p = tm.floorKey(prefer); + if (p != null && (ans[j] == -1 || ans[j] - prefer >= prefer - p)) { + ans[j] = p; + } + } + return ans; + } +} \ No newline at end of file diff --git a/solution/1800-1899/1847.Closest Room/Solution.py b/solution/1800-1899/1847.Closest Room/Solution.py new file mode 100644 index 0000000000000..8923766e34777 --- /dev/null +++ b/solution/1800-1899/1847.Closest Room/Solution.py @@ -0,0 +1,26 @@ +from sortedcontainers import SortedList + + +class Solution: + def closestRoom( + self, rooms: List[List[int]], queries: List[List[int]] + ) -> List[int]: + rooms.sort(key=lambda x: x[1]) + k = len(queries) + idx = sorted(range(k), key=lambda i: queries[i][1]) + ans = [-1] * k + i, n = 0, len(rooms) + sl = SortedList(x[0] for x in rooms) + for j in idx: + prefer, minSize = queries[j] + while i < n and rooms[i][1] < minSize: + sl.remove(rooms[i][0]) + i += 1 + if i == n: + break + p = sl.bisect_left(prefer) + if p < len(sl): + ans[j] = sl[p] + if p and (ans[j] == -1 or ans[j] - prefer >= prefer - sl[p - 1]): + ans[j] = sl[p - 1] + return ans