-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathCount_inversions.cpp
89 lines (78 loc) · 2.3 KB
/
Count_inversions.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
78
79
80
81
82
83
84
85
86
87
88
89
// Copyright (c) 2013 Elements of Programming Interviews. All rights reserved.
#include <algorithm>
#include <cassert>
#include <iostream>
#include <random>
#include <vector>
using std::cout;
using std::default_random_engine;
using std::endl;
using std::random_device;
using std::uniform_int_distribution;
using std::vector;
int count_inversions_helper(vector<int>& A, int start, int end);
int merge(vector<int>& A, int start, int mid, int end);
// @include
int count_inversions(vector<int> A) {
return count_inversions_helper(A, 0, A.size());
}
int count_inversions_helper(vector<int>& A, int start, int end) {
if (end - start <= 1) {
return 0;
}
int mid = start + ((end - start) >> 1);
return count_inversions_helper(A, start, mid) +
count_inversions_helper(A, mid, end) + merge(A, start, mid, end);
}
int merge(vector<int>& A, int start, int mid, int end) {
vector<int> sorted_A;
int left_start = start, right_start = mid, inver_count = 0;
while (left_start < mid && right_start < end) {
if (A[left_start] <= A[right_start]) {
sorted_A.emplace_back(A[left_start++]);
} else {
// A[left_start:mid - 1] will be the inversions.
inver_count += mid - left_start;
sorted_A.emplace_back(A[right_start++]);
}
}
copy(A.begin() + left_start, A.begin() + mid, back_inserter(sorted_A));
copy(A.begin() + right_start, A.begin() + end, back_inserter(sorted_A));
// Update A with sorted_A.
copy(sorted_A.begin(), sorted_A.end(), A.begin() + start);
return inver_count;
}
// @exclude
// O(n^2) check of inversions
template <typename T>
int n_2_check(const vector<T>& A) {
int count = 0;
for (size_t i = 0; i < A.size(); ++i) {
for (size_t j = i + 1; j < A.size(); ++j) {
if (A[i] > A[j]) {
++count;
}
}
}
cout << count << endl;
return count;
}
int main(int argc, char* argv[]) {
default_random_engine gen((random_device())());
for (int times = 0; times < 1000; ++times) {
int n;
if (argc == 2) {
n = atoi(argv[1]);
} else {
uniform_int_distribution<int> dis(1, 10000);
n = dis(gen);
}
vector<int> A;
for (size_t i = 0; i < n; ++i) {
uniform_int_distribution<int> dis(-1000000, 1000000);
A.emplace_back(dis(gen));
}
assert(n_2_check(A) == count_inversions(A));
}
return 0;
}