문제 링크
요약
- DSU 로 풀면 된다.
최종
결과
- Path 가 연결된 애들끼리 묶는 방식으로 DSU 를 사용해 풀면 된다.
- ‘연결된 애들’ 을 찾는것도 간편하다. 만약
nums[i + 1] - nums[i] <= maxDiff라면i + 1와i를 모두 같은 set 에 넣으면 된다. - 이렇게만 해도 되는 이유는 다음과 같다:
nums[i + 1] - nums[i] > maxDiff인데i와i + 1이 다른놈j를 거쳐서 같은 set 에 들어가도록 하는j가 존재하는지 알아보자.j < i라면,j를 거쳐서i와i + 1가 같은 set 에 들어가려면 (a):nums[i] - nums[j] <= maxDiff이고 (b):nums[i + 1] - nums[j] <= maxDiff여야 한다.- (b) 의 양변에
nums[i] - nums[j]를 빼보자. 그럼nums[i + 1] - nums[i] <= maxDiff - (nums[i] - nums[j])가 된다. - 우선 좌변은
nums[i - 1] - nums[i] > maxDiff라고 가정했기 때문에maxDiff보다 크다. - 하지만 우변은 (a) 에 의하면
nums[i] - nums[j] <= maxDiff이므로maxDiff - (maxDiff 보다 작은놈)이 되어maxDiff보다 작다.- 또한,
nums[i] - nums[j] < 0일 수도 없다.nums는 오름차순정렬되어있고j < i이기 때문.
- 또한,
- 따라서 모순되기 때문에, 이걸 만족하는
j는 존재하지 않는다.
i < j < i + 1인j도 없다.j는 자연수이기 때문.i + 1 < j인 경우에도,j < i와 유사한 방식으로j가 존재하지 않음을 증명할 수 있다.
- ‘연결된 애들’ 을 찾는것도 간편하다. 만약
- 결과적으로 DSU 만 잘 구현해주면 이 문제는 금방 풀린다:
class DisjointSet {
vector<int> parent;
vector<int> height;
public:
DisjointSet(int n) {
parent = vector<int>(n);
height = vector<int>(n, 1);
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
void unionSet(int elem1, int elem2) {
int set1 = findSet(elem1);
int set2 = findSet(elem2);
if (set1 == set2) {
return;
}
if (height[set1] == height[set2]) {
parent[set2] = set1;
height[set1]++;
} else if (height[set1] < height[set2]) {
parent[set1] = set2;
} else /* (height[set1] > height[set2]) */ {
parent[set2] = set1;
}
}
int findSet(int elem) {
while (elem != parent[elem]) {
elem = parent[elem];
}
return elem;
}
};
class Solution {
public:
vector<bool> pathExistenceQueries(int n, vector<int>& nums, int maxDiff, vector<vector<int>>& queries) {
DisjointSet ds(n);
int qs = queries.size();
vector<bool> ret(qs);
for (int i = 0; i < n - 1; i++) {
if (nums[i + 1] - nums[i] <= maxDiff) {
ds.unionSet(i, i + 1);
}
}
for (int i = 0; i < qs; i++) {
ret[i] = ds.findSet(queries[i][0]) == ds.findSet(queries[i][1]);
}
return ret;
}
};