160 lines
4.5 KiB
C++
160 lines
4.5 KiB
C++
/*
|
|
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;
|
|
}}
|