median_stream.cpp

This commit is contained in:
2021-01-30 13:18:09 +00:00
parent 1a17b9fe6c
commit c640548c05
2 changed files with 159 additions and 3 deletions

View File

@@ -0,0 +1,159 @@
/*
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
VIM: let b:cf5run="{OUT}"
VIM-: let b:cppflags=g:Iboost.g:Itbb
VIM-: let b:ldflags=g:Lboost.g:Ltbb
VIM-: let b:ldlibpath=g:Bboost.g:Btbb
*/
#include <iostream>
#include <exception>
#include <chrono>
#include <vector>
#include <algorithm>
/*
Median Stream
You're given a list of n integers arr[0..(n-1)]. You must compute a list
output[0..(n-1)] such that, for each index i (between 0 and n-1, inclusive),
output[i] is equal to the median of the elements arr[0..i] (rounded down to
the nearest integer).
The median of a list of integers is defined as follows. If the integers were
to be sorted, then:
If there are an odd number of integers, then the median is equal to the
middle integer in the sorted order.
Otherwise, if there are an even number of integers, then the median is equal
to the average of the two middle-most integers in the sorted order.
Input
n is in the range [1, 1,000,000].
Each value arr[i] is in the range [1, 1,000,000].
Output
Return a list of n integers output[0..(n-1)], as described above.
Example 1
n = 4
arr = [5, 15, 1, 3]
output = [5, 10, 5, 4]
The median of [5] is 5, the median of [5, 15] is (5 + 15) / 2 = 10,
the median of [5, 15, 1] is 5, and the median of [5, 15, 1, 3] is (3 + 5) / 2 = 4.
Example 2
n = 2
arr = [1, 2]
output = [1, 1]
The median of [1] is 1,
the median of [1, 2] is (1 + 2) / 2 = 1.5 (which should be rounded down to 1).
*/
std::vector<int> findMedian(std::vector <int> arr) {
// Write your code here
std::vector<int> r;
std::vector<int> l;
for (size_t i = 0; i < arr.size(); ++i){
l.push_back(arr[i]);
std::push_heap(l.begin(), l.end());
if (l.size() > ((i+1)/2+1)){
std::pop_heap(l.begin(), l.end());
l.resize(l.size()-1);
}
if ((i+1)%2){
r.push_back(l[0]);
} else if (l.size() == 2){
r.push_back( (l[0]+l[1])/2 );
} else {
r.push_back( (l[0]+std::max(l[1],l[2]))/2 );
}
}
return r;
}
// These are the tests we use to determine if the solution is correct.
// You can add your own at the bottom, but they are otherwise not editable!
void printIntegerVector(std::vector <int> array) {
int size = array.size();
std::cout << "[";
for (int i = 0; i < size; i++) {
if (i != 0) {
std::cout << ", ";
}
std::cout << array[i];
}
std::cout << "]";
}
int test_case_number = 1;
void check(std::vector <int>& expected, std::vector <int>& output) {
int expected_size = expected.size();
int output_size = output.size();
bool result = true;
if (expected_size != output_size) {
result = false;
}
for (int i = 0; i < std::min(expected_size, output_size); i++) {
result &= (output[i] == expected[i]);
}
const char* rightTick = "PASS - ";
const char* wrongTick = "FAIL - ";
if (result) {
std::cout << rightTick << "Test #" << test_case_number << "\n";
}
else {
std::cout << wrongTick << "Test #" << test_case_number << ": Expected ";
printIntegerVector(expected);
std::cout << " Your output: ";
printIntegerVector(output);
std::cout << std::endl;
}
test_case_number++;
}
int main ( void )
{try{
auto begin = std::chrono::high_resolution_clock::now();
{
std::vector <int> arr_1{5, 15, 1, 3};
std::vector <int> expected_1{5, 10, 5, 4};
std::vector <int> output_1 = findMedian(arr_1);
check(expected_1, output_1);
}{
std::vector <int> arr_2{2, 4, 7, 1, 5, 3};
std::vector <int> expected_2{2, 3, 4, 3, 4, 3};
std::vector <int> output_2 = findMedian(arr_2);
check(expected_2, output_2);
}{
std::vector <int> arr_2{2, 4, 7, 1, 5};
std::vector <int> expected_2{2, 3, 4, 3, 4};
std::vector <int> output_2 = findMedian(arr_2);
check(expected_2, output_2);
}{
std::vector <int> arr_2{2, 4, 7, 1, 5, 3, 4};
std::vector <int> expected_2{2, 3, 4, 3, 4, 3, 4 };
std::vector <int> output_2 = findMedian(arr_2);
check(expected_2, output_2);
}
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> seconds = end - begin;
std::cout << "Time: " << seconds.count() << std::endl;
return 0;
}
catch ( const std::exception& e )
{
std::cerr << std::endl
<< "std::exception(\"" << e.what() << "\")." << std::endl;
return 2;
}
catch ( ... )
{
std::cerr << std::endl
<< "unknown exception." << std::endl;
return 1;
}}