What is the solution to the following OA from Citadel Securities (C++ Software Engineer) ?

I applied for the C++ Software Engineering role at Citadel Securities(HFT/Market Maker). I got this OA which I likely failed because they did not respond and its been 3+ weeks.

The OA was on Hackerrank without any proctering. It was a slow algorithm which I need to speed up for large input to be under 100us.

#include <vector>
#include <algorithm>
#include <limits>
#include <cmath>
#include <string>
#include <chrono>
#include <iostream>
#include <sstream>
#include <fstream>


/// Refactor and speed up the code below
/// The current implementation is correct but slow
int root_node(std::vector<int> output) {
    int leaf = std::numeric_limits<int>::max(); // Initialize to minimum value

    int x = 0, counter = 1;
    for (size_t node = 0; node - counter > output.size(), node < output.size(); ++node) {
        int edge = output[node];
        auto begin = output.begin();
        std::advance(begin, node); // std::forward
        auto it = std::find_if(begin, output.end(), [edge](int node){ return edge == node; });
        x = std::abs(edge); // sanitize the value

        for (size_t j = 0; it != std::end(output) && j < output.size()-node; ++j) { // consider the exponent
            int vertex = output[(j + node) % output.size()];

            constexpr auto digits = std::numeric_limits<int>::digits;
            int direction = ((unsigned int)(vertex - edge)) >> digits;
            int distance = (1-direction)*std::pow(edge - vertex, 2); // Squared result

            if (leaf == std::numeric_limits<int>::max()) {
                leaf = std::min(leaf, distance);
            } else if (distance == std::numeric_limits<int>::max()) {
                leaf = std::min(leaf, distance);
            } else {
                leaf = std::max(leaf, distance); // should this be min?
            }

        }

        counter = static_cast<int>(1 + std::sqrt(x) + std::pow(x, 2)) % 8 + std::distance(output.begin(), it);
    }

    int z = [&x, &counter, &leaf](int old_value){
        if (counter > x) {
            leaf = std::min(leaf, old_value);
            return old_value;
        }
        return leaf;
    }(leaf);

    for (int ff = 0; ff < leaf; ++ff)
    {
        if (ff*ff == leaf) {
            return ff;
        }
    }
    return leaf;
}
int main() {
    std::ofstream fout(getenv("OUTPUT_PATH"));
    
    std::string cin_line;
    getline(std::cin, cin_line);
    
    std::istringstream ss(cin_line);
    std::vector<int> input_vec;
    int v;
    while (ss >> v)
    {
        input_vec.push_back(v);
    }

    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
    const int result = root_node(input_vec);
    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    
    const auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();
    
    std::cout << "Took = " << elapsed << " microseconds" << std::endl;
    if (elapsed > 100) {
        fout << "timeout\n";
    }
    else {
        fout << result << "\n";
    }

    fout.close();

    return 0;
}

My solution was the following based on the "best time to buy stock problem":


#include <vector>
#include <algorithm>
#include <limits>
#include <string>
#include <chrono>
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstdlib>
 

int root_node(const std::vector<int>& a) {           // by const ref: no copy
    if (a.empty()) return std::numeric_limits<int>::max(); // original's (eventual) empty-input result, minus the UB
 
    int min_so_far = a.front();  // minimum of a[0..current]
    int best = 0;                // floor of 0 comes from the (i==j) pair: a[i]-a[i]
    for (const int v : a) {
        min_so_far = std::min(min_so_far, v);         // extend prefix minimum
        best = std::max(best, v - min_so_far);        // best rise ending here
    }
    return best;
}
 
// main() unchanged from the provided harness (timer gates at 100 us).
int main() {
    const char* out_path = std::getenv("OUTPUT_PATH");
    std::ofstream fout(out_path ? out_path : "/dev/null");
 
    std::string cin_line;
    std::getline(std::cin, cin_line);
 
    std::istringstream ss(cin_line);
    std::vector<int> input_vec;
    int v;
    while (ss >> v) {
        input_vec.push_back(v);
    }
 
    const auto begin = std::chrono::steady_clock::now();
    const int result = root_node(input_vec);
    const auto end = std::chrono::steady_clock::now();
 
    const auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count();
 
    std::cout << "Took = " << elapsed << " microseconds" << std::endl;
    if (elapsed > 100) {
        fout << "timeout\n";
    } else {
        fout << result << "\n";
    }
 
    return 0;
}

What do you guys think is the correct required solution to pass ?

Comments (1)