median_stream.cpp
This commit is contained in:
159
puzzles/training/median_stream.cpp
Normal file
159
puzzles/training/median_stream.cpp
Normal 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;
|
||||
}}
|
||||
Reference in New Issue
Block a user