문제 이해하기
여러 개의 지역(region) 목록이 주어지며, 각 목록의 첫 번째 지역은 해당 목록에 속한 나머지 모든 지역을 포함하는 상위 지역입니다. 즉, 지역 X가 지역 Y를 포함하고 있다면 X는 Y보다 더 넓은(상위의) 지역이고, 정의에 따라 모든 지역은 스스로를 포함합니다.
이러한 구조에서 두 지역 r1과 r2가 주어졌을 때, 두 지역을 모두 포함하는 가장 작은 공통 영역을 찾아야 합니다. 한 지역을 포함하는 상위 지역은 유일하다는 조건이 보장되므로 포함 관계는 트리 형태를 이루며, 정답 역시 항상 하나로 결정됩니다.
예를 들어 입력이 아래와 같고 r1 = 'Quebec', r2 = 'New York'이라면, 두 지역을 모두 포함하는 가장 작은 지역인 'North America'가 출력됩니다.
[["Earth","North America","South America"], ["North America","United States","Canada"], ["United States","New York","Boston"], ["Canada","Ontario","Quebec"], ["South America","Brazil"]] r1 = "Quebec", r2 = "New York"
해결 접근 방법
이 문제는 본질적으로 트리 구조에서 두 노드의 최소 공통 조상(LCA, Lowest Common Ancestor)을 구하는 문제와 같습니다. 각 지역의 부모 정보만 파악하면 되므로, 다음 순서로 간단하게 해결할 수 있습니다.
- 각 지역의 부모를 저장할 map(parent)을 생성합니다.
- x에서 출발해 부모를 따라 루트까지 올라가며, 거치는 모든 지역을 set(chain)에 기록합니다.
- y가 chain에 속할 때까지 y를 부모 방향으로 한 단계씩 이동시킵니다.
- chain에 처음으로 도달한 y가 곧 두 지역의 최소 공통 영역이므로 이를 반환합니다.
알고리즘 단계 정리
- parent라는 이름의 map을 생성합니다.
- i를 0부터 r의 크기까지 반복합니다.
- j를 1부터 r[i]의 크기까지 반복하며 parent[r[i][j]] := r[i][0]을 설정합니다.
- chain이라는 set을 만들고 x를 삽입합니다.
- x가 parent에 존재하는 동안 x := parent[x]로 갱신하고, x를 chain에 삽입합니다.
- y가 chain에 존재하지 않는 동안 y := parent[y]로 갱신합니다.
- y를 반환합니다.
C++ 구현 예제
아래 코드를 통해 실제 동작 과정을 더 잘 이해할 수 있습니다.
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
string findSmallestRegion(vector<vector<string>>& r, string x, string y) {
map < string, string> parent;
for(int i = 0; i < r.size(); i++){
for(int j = 1; j < r[i].size(); j++){
parent[r[i][j]] = r[i][0];
}
}
set <string> chain;
chain.insert(x);
while(parent.find(x)!=parent.end()){
x = parent[x];
chain.insert(x);
}
while(chain.find(y)==chain.end()){
y = parent[y];
}
return y;
}
};
main(){
vector<vector<string>> v = {
{"Earth","North America","South America"},
{"North America","United States","Canada"},
{"United States","New York","Boston"},
{"Canada","Ontario","Quebec"},{"South America","Brazil"}
};
Solution ob;
cout << (ob.findSmallestRegion(v, "Quebec", "New York"));
}
입력 및 출력 확인
입력
[["Earth","North America","South America"],["North America","United States","Canada"], ["United States","New York","Boston"],["Canada","Ontario","Quebec"],["South America","Brazil"]] "Quebec" "New York"
출력
North America
시간 및 공간 복잡도
부모 맵을 구성하는 데 전체 지역 수 N에 비례하는 시간이 소요되고, 이후 두 지역을 루트 방향으로 올리는 과정은 트리의 최대 깊이 H에 비례합니다. std::map과 std::set의 연산이 로그 시간을 요구하므로 전체 시간 복잡도는 O(N log N), 공간 복잡도는 O(N)입니다. unordered_map과 unordered_set을 사용하면 평균적으로 더 빠른 처리가 가능합니다.