Skip to content

feat: add solutions to lc problem: No.1847 #1558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions solution/1800-1899/1847.Closest Room/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,196 @@

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

**方法一:离线查询 + 有序集合 + 二分查找**

我们注意到,查询的顺序并不影响答案,而且题目中涉及到房间面积的大小关系,因此,我们可以将查询按照最小面积从小到大排序,这样我们就可以从小到大依次处理每个查询。另外,我们也将房间按照面积从小到大排序。

接下来,我们创建一个有序列表,将所有房间的编号加入有序列表中。

然后,我们从小到大依次处理每个查询。对于每个查询,我们首先将所有面积小于等于当前查询的最小面积的房间从有序列表中移除。然后,我们在剩余的房间中,使用二分查找找到最接近当前查询的房间编号。如果不存在这样的房间,那么我们就返回 $-1$。

时间复杂度 $O(n \times \log n + k \times \log k)$,空间复杂度 $O(n + k)$。其中 $n$ 和 $k$ 分别是房间数和查询数。

<!-- tabs:start -->

### **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<Integer, Integer> 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<int> closestRoom(vector<vector<int>>& rooms, vector<vector<int>>& queries) {
int n = rooms.size();
int k = queries.size();
sort(rooms.begin(), rooms.end(), [](const vector<int>& a, const vector<int>& b) {
return a[1] < b[1];
});
vector<int> 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<int> ans(k, -1);
int i = 0;
multiset<int> 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
}
```

### **...**
Expand Down
166 changes: 165 additions & 1 deletion solution/1800-1899/1847.Closest Room/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<Integer, Integer> 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<int> closestRoom(vector<vector<int>>& rooms, vector<vector<int>>& queries) {
int n = rooms.size();
int k = queries.size();
sort(rooms.begin(), rooms.end(), [](const vector<int>& a, const vector<int>& b) {
return a[1] < b[1];
});
vector<int> 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<int> ans(k, -1);
int i = 0;
multiset<int> 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
}
```

### **...**
Expand Down
Loading