#include <iostream>
#include <vector>

//Find Majority element i.e. the element that occurs more than 1/2 of the array
// Worst Case Complexity :  O(n)
template <typename DataType>
DataType FindMajorityElement(std::vector<DataType> arr) {
    // Modified BOYERS ALGORITHM with forward and reverse passes
    // Count will stay positive if there is a majority element
    auto GetMajority = [](auto seq_begin, auto seq_end) -> DataType{
        int count = 1;
        DataType majority = *(seq_begin);
        for (auto itr = seq_begin+1; itr != seq_end; ++itr) {
            count += (*itr == majority) ? 1 : -1;
            if (count <= 0) {   // Flip the majority and set the count to zero whenever it falls below zero
                majority = *(itr);
                count = 0;
            }
        }
        return majority;
    };
    DataType majority1 = GetMajority(arr.begin(), arr.end());
    DataType majority2 = GetMajority(arr.rbegin(), arr.rend());
    int maj1_count = 0, maj2_count = 0;
    // Check if any of the the majority elements is really the majority
    for (const auto& itr: arr) {
        maj1_count += majority1 == itr ? 1 : 0;
        maj2_count += majority2 == itr ? 1 : 0;
    }
    if (maj1_count >= arr.size()/2)
        return majority1;
    if (maj2_count >= arr.size()/2)
        return majority2;
    // else return -1
    return -1;
}

int main() {
    using namespace std;
    std::cout <<  FindMajorityElement(std::vector<int> { 1, 10, 2, 10, 1, 10, 4, 10, 5, 10 }) << endl;
    std::cout <<  FindMajorityElement(std::vector<int> { 10, 1, 10, 2, 10, 1, 10, 4, 10, 5 }) << endl;
    std::cout <<  FindMajorityElement(std::vector<int> { 1, 2, 1, 10, 10, 10, 10, 4, 10, 5 }) << endl;
    std::cout <<  FindMajorityElement(std::vector<int> { 1, 1, 1, 10, 10, 10, 10, 10, 5, 4 }) << endl;
    std::cout <<  FindMajorityElement(std::vector<float> { 1.0f, 1.0f, 1.0f, 10.f, 10.0f, 10.0f, 10, 10, 5, 4 }) << endl;
    return 0;
}

