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