Skip to content

Commit f7e4a87

Browse files
authored
feat: add solutions to lc problem: No.1847 (doocs#1558)
No.1847.Closest Room
1 parent acaeeda commit f7e4a87

File tree

6 files changed

+495
-1
lines changed

6 files changed

+495
-1
lines changed

solution/1800-1899/1847.Closest Room/README.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,196 @@
5858

5959
<!-- 这里可写通用的实现逻辑 -->
6060

61+
**方法一:离线查询 + 有序集合 + 二分查找**
62+
63+
我们注意到,查询的顺序并不影响答案,而且题目中涉及到房间面积的大小关系,因此,我们可以将查询按照最小面积从小到大排序,这样我们就可以从小到大依次处理每个查询。另外,我们也将房间按照面积从小到大排序。
64+
65+
接下来,我们创建一个有序列表,将所有房间的编号加入有序列表中。
66+
67+
然后,我们从小到大依次处理每个查询。对于每个查询,我们首先将所有面积小于等于当前查询的最小面积的房间从有序列表中移除。然后,我们在剩余的房间中,使用二分查找找到最接近当前查询的房间编号。如果不存在这样的房间,那么我们就返回 $-1$。
68+
69+
时间复杂度 $O(n \times \log n + k \times \log k)$,空间复杂度 $O(n + k)$。其中 $n$ 和 $k$ 分别是房间数和查询数。
70+
6171
<!-- tabs:start -->
6272

6373
### **Python3**
6474

6575
<!-- 这里可写当前语言的特殊实现逻辑 -->
6676

6777
```python
78+
from sortedcontainers import SortedList
79+
6880

81+
class Solution:
82+
def closestRoom(
83+
self, rooms: List[List[int]], queries: List[List[int]]
84+
) -> List[int]:
85+
rooms.sort(key=lambda x: x[1])
86+
k = len(queries)
87+
idx = sorted(range(k), key=lambda i: queries[i][1])
88+
ans = [-1] * k
89+
i, n = 0, len(rooms)
90+
sl = SortedList(x[0] for x in rooms)
91+
for j in idx:
92+
prefer, minSize = queries[j]
93+
while i < n and rooms[i][1] < minSize:
94+
sl.remove(rooms[i][0])
95+
i += 1
96+
if i == n:
97+
break
98+
p = sl.bisect_left(prefer)
99+
if p < len(sl):
100+
ans[j] = sl[p]
101+
if p and (ans[j] == -1 or ans[j] - prefer >= prefer - sl[p - 1]):
102+
ans[j] = sl[p - 1]
103+
return ans
69104
```
70105

71106
### **Java**
72107

73108
<!-- 这里可写当前语言的特殊实现逻辑 -->
74109

75110
```java
111+
class Solution {
112+
public int[] closestRoom(int[][] rooms, int[][] queries) {
113+
int n = rooms.length;
114+
int k = queries.length;
115+
Arrays.sort(rooms, (a, b) -> a[1] - b[1]);
116+
Integer[] idx = new Integer[k];
117+
for (int i = 0; i < k; i++) {
118+
idx[i] = i;
119+
}
120+
Arrays.sort(idx, (i, j) -> queries[i][1] - queries[j][1]);
121+
int i = 0;
122+
TreeMap<Integer, Integer> tm = new TreeMap<>();
123+
for (int[] room : rooms) {
124+
tm.merge(room[0], 1, Integer::sum);
125+
}
126+
int[] ans = new int[k];
127+
Arrays.fill(ans, -1);
128+
for (int j : idx) {
129+
int prefer = queries[j][0], minSize = queries[j][1];
130+
while (i < n && rooms[i][1] < minSize) {
131+
if (tm.merge(rooms[i][0], -1, Integer::sum) == 0) {
132+
tm.remove(rooms[i][0]);
133+
}
134+
++i;
135+
}
136+
if (i == n) {
137+
break;
138+
}
139+
Integer p = tm.ceilingKey(prefer);
140+
if (p != null) {
141+
ans[j] = p;
142+
}
143+
p = tm.floorKey(prefer);
144+
if (p != null && (ans[j] == -1 || ans[j] - prefer >= prefer - p)) {
145+
ans[j] = p;
146+
}
147+
}
148+
return ans;
149+
}
150+
}
151+
```
152+
153+
### **C++**
154+
155+
```cpp
156+
class Solution {
157+
public:
158+
vector<int> closestRoom(vector<vector<int>>& rooms, vector<vector<int>>& queries) {
159+
int n = rooms.size();
160+
int k = queries.size();
161+
sort(rooms.begin(), rooms.end(), [](const vector<int>& a, const vector<int>& b) {
162+
return a[1] < b[1];
163+
});
164+
vector<int> idx(k);
165+
iota(idx.begin(), idx.end(), 0);
166+
sort(idx.begin(), idx.end(), [&](int i, int j) {
167+
return queries[i][1] < queries[j][1];
168+
});
169+
vector<int> ans(k, -1);
170+
int i = 0;
171+
multiset<int> s;
172+
for (auto& room : rooms) {
173+
s.insert(room[0]);
174+
}
175+
for (int j : idx) {
176+
int prefer = queries[j][0], minSize = queries[j][1];
177+
while (i < n && rooms[i][1] < minSize) {
178+
s.erase(s.find(rooms[i][0]));
179+
++i;
180+
}
181+
if (i == n) {
182+
break;
183+
}
184+
auto it = s.lower_bound(prefer);
185+
if (it != s.end()) {
186+
ans[j] = *it;
187+
}
188+
if (it != s.begin()) {
189+
--it;
190+
if (ans[j] == -1 || abs(*it - prefer) <= abs(ans[j] - prefer)) {
191+
ans[j] = *it;
192+
}
193+
}
194+
}
195+
return ans;
196+
}
197+
};
198+
```
199+
200+
### **Go**
201+
202+
```go
203+
func closestRoom(rooms [][]int, queries [][]int) []int {
204+
n, k := len(rooms), len(queries)
205+
sort.Slice(rooms, func(i, j int) bool { return rooms[i][1] < rooms[j][1] })
206+
idx := make([]int, k)
207+
ans := make([]int, k)
208+
for i := range idx {
209+
idx[i] = i
210+
ans[i] = -1
211+
}
212+
sort.Slice(idx, func(i, j int) bool { return queries[idx[i]][1] < queries[idx[j]][1] })
213+
rbt := redblacktree.NewWithIntComparator()
214+
merge := func(rbt *redblacktree.Tree, key, value int) {
215+
if v, ok := rbt.Get(key); ok {
216+
nxt := v.(int) + value
217+
if nxt == 0 {
218+
rbt.Remove(key)
219+
} else {
220+
rbt.Put(key, nxt)
221+
}
222+
} else {
223+
rbt.Put(key, value)
224+
}
225+
}
226+
for _, room := range rooms {
227+
merge(rbt, room[0], 1)
228+
}
229+
i := 0
76230
231+
for _, j := range idx {
232+
prefer, minSize := queries[j][0], queries[j][1]
233+
for i < n && rooms[i][1] < minSize {
234+
merge(rbt, rooms[i][0], -1)
235+
i++
236+
}
237+
if i == n {
238+
break
239+
}
240+
c, _ := rbt.Ceiling(prefer)
241+
f, _ := rbt.Floor(prefer)
242+
if c != nil {
243+
ans[j] = c.Key.(int)
244+
}
245+
if f != nil && (ans[j] == -1 || ans[j]-prefer >= prefer-f.Key.(int)) {
246+
ans[j] = f.Key.(int)
247+
}
248+
}
249+
return ans
250+
}
77251
```
78252

79253
### **...**

solution/1800-1899/1847.Closest Room/README_EN.md

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,177 @@ Query = [2,5]: Room number 3 is the only room with a size of at least 5. The ans
5757
### **Python3**
5858

5959
```python
60-
60+
from sortedcontainers import SortedList
61+
62+
63+
class Solution:
64+
def closestRoom(
65+
self, rooms: List[List[int]], queries: List[List[int]]
66+
) -> List[int]:
67+
rooms.sort(key=lambda x: x[1])
68+
k = len(queries)
69+
idx = sorted(range(k), key=lambda i: queries[i][1])
70+
ans = [-1] * k
71+
i, n = 0, len(rooms)
72+
sl = SortedList(x[0] for x in rooms)
73+
for j in idx:
74+
prefer, minSize = queries[j]
75+
while i < n and rooms[i][1] < minSize:
76+
sl.remove(rooms[i][0])
77+
i += 1
78+
if i == n:
79+
break
80+
p = sl.bisect_left(prefer)
81+
if p < len(sl):
82+
ans[j] = sl[p]
83+
if p and (ans[j] == -1 or ans[j] - prefer >= prefer - sl[p - 1]):
84+
ans[j] = sl[p - 1]
85+
return ans
6186
```
6287

6388
### **Java**
6489

6590
```java
91+
class Solution {
92+
public int[] closestRoom(int[][] rooms, int[][] queries) {
93+
int n = rooms.length;
94+
int k = queries.length;
95+
Arrays.sort(rooms, (a, b) -> a[1] - b[1]);
96+
Integer[] idx = new Integer[k];
97+
for (int i = 0; i < k; i++) {
98+
idx[i] = i;
99+
}
100+
Arrays.sort(idx, (i, j) -> queries[i][1] - queries[j][1]);
101+
int i = 0;
102+
TreeMap<Integer, Integer> tm = new TreeMap<>();
103+
for (int[] room : rooms) {
104+
tm.merge(room[0], 1, Integer::sum);
105+
}
106+
int[] ans = new int[k];
107+
Arrays.fill(ans, -1);
108+
for (int j : idx) {
109+
int prefer = queries[j][0], minSize = queries[j][1];
110+
while (i < n && rooms[i][1] < minSize) {
111+
if (tm.merge(rooms[i][0], -1, Integer::sum) == 0) {
112+
tm.remove(rooms[i][0]);
113+
}
114+
++i;
115+
}
116+
if (i == n) {
117+
break;
118+
}
119+
Integer p = tm.ceilingKey(prefer);
120+
if (p != null) {
121+
ans[j] = p;
122+
}
123+
p = tm.floorKey(prefer);
124+
if (p != null && (ans[j] == -1 || ans[j] - prefer >= prefer - p)) {
125+
ans[j] = p;
126+
}
127+
}
128+
return ans;
129+
}
130+
}
131+
```
132+
133+
### **C++**
134+
135+
```cpp
136+
class Solution {
137+
public:
138+
vector<int> closestRoom(vector<vector<int>>& rooms, vector<vector<int>>& queries) {
139+
int n = rooms.size();
140+
int k = queries.size();
141+
sort(rooms.begin(), rooms.end(), [](const vector<int>& a, const vector<int>& b) {
142+
return a[1] < b[1];
143+
});
144+
vector<int> idx(k);
145+
iota(idx.begin(), idx.end(), 0);
146+
sort(idx.begin(), idx.end(), [&](int i, int j) {
147+
return queries[i][1] < queries[j][1];
148+
});
149+
vector<int> ans(k, -1);
150+
int i = 0;
151+
multiset<int> s;
152+
for (auto& room : rooms) {
153+
s.insert(room[0]);
154+
}
155+
for (int j : idx) {
156+
int prefer = queries[j][0], minSize = queries[j][1];
157+
while (i < n && rooms[i][1] < minSize) {
158+
s.erase(s.find(rooms[i][0]));
159+
++i;
160+
}
161+
if (i == n) {
162+
break;
163+
}
164+
auto it = s.lower_bound(prefer);
165+
if (it != s.end()) {
166+
ans[j] = *it;
167+
}
168+
if (it != s.begin()) {
169+
--it;
170+
if (ans[j] == -1 || abs(*it - prefer) <= abs(ans[j] - prefer)) {
171+
ans[j] = *it;
172+
}
173+
}
174+
}
175+
return ans;
176+
}
177+
};
178+
```
66179
180+
### **Go**
181+
182+
```go
183+
func closestRoom(rooms [][]int, queries [][]int) []int {
184+
n, k := len(rooms), len(queries)
185+
sort.Slice(rooms, func(i, j int) bool { return rooms[i][1] < rooms[j][1] })
186+
idx := make([]int, k)
187+
ans := make([]int, k)
188+
for i := range idx {
189+
idx[i] = i
190+
ans[i] = -1
191+
}
192+
sort.Slice(idx, func(i, j int) bool { return queries[idx[i]][1] < queries[idx[j]][1] })
193+
rbt := redblacktree.NewWithIntComparator()
194+
merge := func(rbt *redblacktree.Tree, key, value int) {
195+
if v, ok := rbt.Get(key); ok {
196+
nxt := v.(int) + value
197+
if nxt == 0 {
198+
rbt.Remove(key)
199+
} else {
200+
rbt.Put(key, nxt)
201+
}
202+
} else {
203+
rbt.Put(key, value)
204+
}
205+
}
206+
for _, room := range rooms {
207+
merge(rbt, room[0], 1)
208+
}
209+
i := 0
210+
211+
for _, j := range idx {
212+
prefer, minSize := queries[j][0], queries[j][1]
213+
for i < n && rooms[i][1] < minSize {
214+
merge(rbt, rooms[i][0], -1)
215+
i++
216+
}
217+
if i == n {
218+
break
219+
}
220+
c, _ := rbt.Ceiling(prefer)
221+
f, _ := rbt.Floor(prefer)
222+
if c != nil {
223+
ans[j] = c.Key.(int)
224+
}
225+
if f != nil && (ans[j] == -1 || ans[j]-prefer >= prefer-f.Key.(int)) {
226+
ans[j] = f.Key.(int)
227+
}
228+
}
229+
return ans
230+
}
67231
```
68232

69233
### **...**

0 commit comments

Comments
 (0)