// 并查集 + 离散化:
// 将涉及的点映射到[0,n], 并查集中find(x)即x所在集合的祖先,表示[x, find(x)-1]已标记答案并删除,下一个未删除的点为find(x)
// 区间按长度从小到大排序,从小到大枚举,包含在区间的点的答案即为此区间长度,因此在并查集中删除这些点(p[x] = x + 1)
class Solution {
int[] xs = new int[300010]; // 离散化后,第i个数对应的值
int[] p = new int[300010]; // 并查集
int[] w = new int[300010]; // 每个点的答案
public int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
// 离散化:点加入set自动去重排序,再将点依次放入map
Set<Integer> set = new TreeSet();
Map<Integer, Integer> map = new HashMap();
public int[] minInterval(int[][] intervals, int[] queries) {
for (int[] interval : intervals) {
set.add(interval[0]);
set.add(interval[1]);
}
for (int query : queries) set.add(query);
int j = 0;
for (int v : set) {
map.put(v, j);
xs[j] = v;
j ++;
}
int n = j;
// 初始化并查集和答案集
for (int i = 0; i < n + 1; i++) {
p[i] = i;
w[i] = -1;
}
// 区间按长度从小到大排序
Arrays.sort(intervals, (a, b) -> (a[1] - a[0] + 1) - (b[1] - b[0] + 1));
for (int[] interval : intervals) { // 遍历区间
int l = interval[0], r = interval[1];
int len = r - l + 1; // 区间长度
// 对应离散化后的下标
l = map.get(l);
r = map.get(r);
// 标记[l, r] 中未标记答案的点
while(find(l) <= r) { // 下一个未标记的点为find(l)
l = find(l);
p[l] = l + 1; // 删除点l,即下一个未标记的点为l+1
w[l] = len;
}
}
int k = queries.length;
int[] res = new int[k];
for (int i = 0; i < k; i++) res[i] = w[map.get(queries[i])];
return res;
}
}
LeetCode1851. 包含每个查询的最小区间(第239场周赛第四题)
最新推荐文章于 2022-11-28 15:29:54 发布