-
Notifications
You must be signed in to change notification settings - Fork 25
/
CountDistinctSlices.cpp
77 lines (66 loc) · 2.77 KB
/
CountDistinctSlices.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// https://app.codility.com/programmers/lessons/15-caterpillar_method/count_distinct_slices/
//
// Task Score: 100%
// Correctness: 100%
// Performance: 100%
// Detected time complexity: O(N)
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
int solution(int M, vector<int> &A) {
const int N = A.size();
// M is [0..100000], so need to account for 0
// This will give me time complexity O(N) and space complexity O(M)
// I could use a hash but that would give me time complexity O(N) but
// worst case space complexity is still O(M), just going to go for O(N) and O(M)
vector<int>Z(M+1, 0);
// Remember that slices of length 1 count, which means we will
// always have at least N distinct slices. I do not have to count them
// specifically, as the method below will count them
long long int distinctSlices = 0;
// track where start of current sequence is
int j = 0;
// track how long current sequence is.
long long int sequenceLength = 0;
// Go through all items
for ( int i=0; i<N; i++) {
// Everytime we loop we need to add the current sequenceLength
// to the count. This is done by observation. At first I waited
// until I found a duplicate, and then I added x*(x+1)/2 but this
// double counted elements. Then I observed everytime I incremented
// a number, I needed to add that many combinations, and I do
// not double count what I have already seen.
Z[A[i]]++;
if ( Z[A[i]] < 2 ) {
sequenceLength++;
distinctSlices += sequenceLength;
continue;
}
// then start incrementing j and removing items from
// the duplicate list. There is going to be one item in the
// list with a duplicate (value == 2), and keep
// incrementing j/removing sequenceLength until we
// remove it or get to i
bool removedDuplicate = false;
while ( (j < i) && !removedDuplicate ) {
// remove A[j] from list
Z[A[j]]--;
// This will either be 0 (because it was not a duplicate) or else 1
// (because it was the duplicate). Continue until we remove the
// duplicate
if ( Z[A[j]] ) {
// New distinct element, so add sequence length as before
distinctSlices += sequenceLength;
removedDuplicate = true;
} else {
// haven't removed duplicate yet, continue along
sequenceLength--;
}
j++;
}
}
// If the number of distinct slices is greater than 1000000000,
// then function should return 1000000000;
return std::min(distinctSlices, (long long int)1000000000);
}