Skip to content

Commit 6d8fa87

Browse files
Cc618abranhe
authored andcommitted
Added math/median_subarray
1 parent d24c342 commit 6d8fa87

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

algorithms/math/median_subarray.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// * Description :
2+
// Given an array of integers nums and the length of subarrays
3+
// print all medians of each subarrays
4+
// * Example :
5+
// Array : [5,2,2,7,3,7,9,0,2,3], Subarray length : 5
6+
// Should print : 3 3 7 7 3 3
7+
// The first subarray is [5, 2, 2, 7, 3], then the median is 3
8+
// * Complexity :
9+
// O(N log K) time, O(N) space, N = array.size(), K = subarray.size()
10+
11+
#include <iostream>
12+
#include <vector>
13+
#include <set>
14+
15+
using namespace std;
16+
17+
// Method :
18+
// Firstly initialize two heaps, lower and upper such that
19+
// abs(lower.size() - upper.size()) <= 1 &&
20+
// median >= lower[i] && median <= upper[i]
21+
// The median is either the average of the two top values
22+
// or the top value of the greatest heap.
23+
// To add a value add it to the smallest heap and swap tops
24+
// if lower and upper don't follow the first condition.
25+
// To remove a value we find it, remove it and add the top of
26+
// the other heap to the updated heap (sizes are now the same).
27+
// We just remove and then add an item for each index of [0, N-k)
28+
// to simulate a sliding window.
29+
vector<double> medianSubarray(vector<int>& values, int k) {
30+
// We use long long instead of int to avoid overflows
31+
// median >= lower[i] && median <= upper[i]
32+
multiset<long long, greater<long long>> lower;
33+
multiset<long long> upper;
34+
vector<double> medians;
35+
36+
// Initialize lower and upper
37+
for (int i = 0; i < k; ++i) {
38+
if (lower.size() <= upper.size())
39+
lower.insert(values[i]);
40+
else
41+
upper.insert(values[i]);
42+
43+
// Swap values if heaps aren't balanced
44+
if (!lower.empty() && !upper.empty() &&
45+
*lower.begin() > *upper.begin()) {
46+
long long tmp = *lower.begin();
47+
lower.erase(lower.begin());
48+
lower.insert(*upper.begin());
49+
upper.erase(upper.begin());
50+
upper.insert(tmp);
51+
}
52+
}
53+
54+
// To get the median inline
55+
#define GET_MEDIAN (lower.size() == upper.size() ? \
56+
(*lower.begin() + (*upper.begin() - *lower.begin()) * .5) : \
57+
lower.size() > upper.size() ? *lower.begin() : *upper.begin())
58+
59+
medians.push_back(GET_MEDIAN);
60+
61+
for (int i = 0; i < values.size() - k; ++i) {
62+
// Remove the i item
63+
bool removed = false;
64+
if (!lower.empty() && values[i] <= *lower.begin()) {
65+
// Remove it
66+
auto target = lower.find(values[i]);
67+
if (target != lower.end()) {
68+
lower.erase(target);
69+
removed = true;
70+
71+
// Insert the top of the other heap to the updated heap
72+
if (!upper.empty()) {
73+
lower.insert(*upper.begin());
74+
upper.erase(upper.begin());
75+
}
76+
}
77+
}
78+
79+
if (!removed) {
80+
// Remove it
81+
upper.erase(upper.find(values[i]));
82+
83+
// Insert the top of the other heap to the updated heap
84+
if (!lower.empty()) {
85+
upper.insert(*lower.begin());
86+
lower.erase(lower.begin());
87+
}
88+
}
89+
90+
// Add the i + k item
91+
if (lower.size() <= upper.size())
92+
lower.insert(values[i + k]);
93+
else
94+
upper.insert(values[i + k]);
95+
96+
// Swap values if heaps aren't balanced
97+
if (!lower.empty() && !upper.empty() &&
98+
*lower.begin() > *upper.begin()) {
99+
long long tmp = *lower.begin();
100+
lower.erase(lower.begin());
101+
lower.insert(*upper.begin());
102+
upper.erase(upper.begin());
103+
upper.insert(tmp);
104+
}
105+
106+
medians.push_back(GET_MEDIAN);
107+
}
108+
109+
return medians;
110+
}
111+
112+
int main() {
113+
vector<pair<int, vector<int>>> dataset = {
114+
{5, {5,2,2,7,3,7,9,0,2,3}},
115+
{3, {1,3,-1,-3,5,3,6,7}},
116+
{1, {1,2}},
117+
{2, {2147483647,2147483647}},
118+
};
119+
120+
// Should be :
121+
// 3 3 7 7 3 3
122+
// 1 -1 -1 3 5 6
123+
// 1 2
124+
// 2.14748e+09
125+
for (auto test : dataset) {
126+
auto y = medianSubarray(test.second, test.first);
127+
for (double median : y)
128+
cout << median << " ";
129+
130+
cout << endl;
131+
}
132+
133+
return 0;
134+
}

0 commit comments

Comments
 (0)