1+ /*
2+ longest-consecutive-sequence
3+ 요구사항: 주어진 비정렬 배열에서 가장 긴 연속 수열의 길이를 O(N)에 구하라.
4+ 접근 1: 가장 단순한 방법은 정렬 후 스캔하여 가장 긴 연속 구간을 찾는 것이다.
5+ 정렬 비용 O(NlogN)에 스캔 O(N)으로 총 O(NlogN)이다. 비용 초과.
6+ 접근 2: 정렬하지 않고, 인접한 연속 원소 수열을 '하나의 덩어리'로 취급하기 위해 union-find할 수 있다.
7+ 중복 원소는 무시한다.
8+ 입력 x에 대해 x-1의 유니온을 찾는다.
9+ 그러한 유니온이 존재하면 x를 추가한다. 그 이후 x+1 유니온이 존재하면 통합한다.
10+ 그러한 유니온이 존재하지 않으면 x+1 유니온을 찾는다.
11+ 그러한 유니온이 존재하면 x를 추가한다.
12+ 인접한 앞 뒤 유니온이 존재하지 않으면 입력을 새로운 root union으로 초기화한다.
13+
14+ 비용:
15+ 경로 압축과 높이 최소화 최적화를 적용하면, find 비용은 O(α(N))으로 최대 입력 N=10^5에 대해서 한 자리 상수만큼 충분히 낮다.
16+ 유니온의 통합 비용은 O(1)이다.
17+ N개의 입력에 대해 O(1) 연산을 상수 ㅣ 수행하므로 유니온 빌딩 시간 복잡도는 O(N)이다.
18+ 사이즈 리스트를 스캔하여 가장 큰 유니온의 크기를 구한다. 이는 O(K) where K <= N이다.
19+ 따라서 총 시간 복잡도는 O(N)이다.
20+ 공간 복잡도도 입력 범위의 상수배이므로 O(N)이다.
21+ */
22+
23+ #include < unordered_map>
24+ #include < vector>
25+
26+ #define max (a, b ) ((a) > (b) ? (a) : (b))
27+
28+ class Solution {
29+ public:
30+ std::unordered_map<int , int > parent;
31+ std::unordered_map<int , int > size;
32+
33+ int find (int x) {
34+ if (x == parent[x]) return x;
35+ return parent[x] = find (parent[x]); // path compression
36+ }
37+ void union_sets (int x, int y) {
38+ int px = find (x);
39+ int py = find (y);
40+
41+ if (px == py) return ;
42+
43+ // min height optimization
44+ if (size[px] > size[py]) {
45+ size[px] += size[py];
46+ parent[py] = px;
47+ } else {
48+ size[py] += size[px];
49+ parent[px] = py;
50+ }
51+ }
52+ int longestConsecutive (std::vector<int >& nums) {
53+ // build union
54+ for (auto it = nums.begin (); it != nums.end (); it++) {
55+ int x = *it;
56+
57+ if (parent.find (x) != parent.end ())
58+ continue ;
59+
60+ if (parent.find (x - 1 ) != parent.end ()) {
61+ parent[x] = find (x - 1 );
62+ size[parent[x]]++;
63+ if (parent.find (x + 1 ) != parent.end ()) {
64+ union_sets (x, x + 1 );
65+ }
66+ } else if (parent.find (x + 1 ) != parent.end ()) {
67+ parent[x] = find (x + 1 );
68+ size[parent[x]]++;
69+ } else {
70+ parent[x] = x;
71+ size[x] = 1 ;
72+ }
73+ }
74+
75+ // find largest set
76+ int max_size = 0 ;
77+ for (auto it = size.begin (); it != size.end (); it++) {
78+ auto sz = it->second ;
79+ max_size = max (max_size, sz);
80+ }
81+ return max_size;
82+ }
83+ };
0 commit comments