Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 19 additions & 72 deletions src/1_Arrays/majority_element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,16 @@
*
* A majority element is an element that appears more than n/2 times in an array
* of size n. If such an element exists, return it; otherwise, indicate no majority.
*
* Example:
* Input: [2, 2, 2, 1, 1]
* Output: 2
*
* Input: [1, 2, 3, 4, 5]
* Output: No majority
*/
#include <algorithm>
#include <cassert>
#include <iostream>
#include <random>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <vector>

// ---- Utility ----
bool isMajority(const std::vector<int>& arr, int candidate) {
return std::count(arr.begin(), arr.end(), candidate) * 2 > static_cast<int>(arr.size());
}
Expand All @@ -42,94 +36,47 @@ int majorityCounting(const std::vector<int>& arr) {
return candidate;
}

// Quickselect-based partition (average O(n), modifies array)
int randomIndex(int start, int end) {
static std::mt19937 gen{std::random_device{}()};
std::uniform_int_distribution<> dist(start, end);
return dist(gen);
}

int partition(std::vector<int>& arr, int start, int end) {
int pivotIdx = randomIndex(start, end);
std::swap(arr[pivotIdx], arr[end]);
int store = start;
for (int i = start; i < end; ++i) {
if (arr[i] < arr[end]) {
std::swap(arr[i], arr[store++]);
}
}
std::swap(arr[store], arr[end]);
return store;
}

int majorityPartition(std::vector<int>& arr) {
// Finds and returns the majority element using the frequency dictionary approach (O(n) time, O(n) space).
int majorityFrequency(const std::vector<int>& arr) {
if (arr.empty()) throw std::invalid_argument("Array is empty.");
int mid = arr.size() / 2, lo = 0, hi = arr.size() - 1;
while (true) {
int idx = partition(arr, lo, hi);
if (idx == mid) break;
if (idx < mid) lo = idx + 1;
else hi = idx - 1;
std::unordered_map<int, int> freq;
const int n = static_cast<int>(arr.size());
for (int v : arr) {
int c = ++freq[v]; // increment the count for v
if (c * 2 > n) return v; // early exit if v is majority
}
int candidate = arr[mid];
if (!isMajority(arr, candidate))
throw std::invalid_argument("No majority exists.");
return candidate;
throw std::invalid_argument("No majority exists.");
}

// ---- Testing infrastructure ----

// ---- Testing infrastructure ----
struct TestCase {
std::string name;
std::vector<int> arr;
bool expectException;
int expected; // only meaningful if expectException == false
};

void testMajorityCounting(const std::vector<TestCase>& cases) {
std::cout << "=== Testing majorityCounting ===\n";
for (auto& tc : cases) {
bool passed = false;
try {
int result = majorityCounting(tc.arr);
if (!tc.expectException && result == tc.expected) {
passed = true;
}
} catch (const std::invalid_argument&) {
if (tc.expectException) passed = true;
}
std::cout
<< tc.name
<< " -> " << (passed ? "PASS" : "FAIL")
<< "\n";
assert(passed);
}
std::cout << "\n";
}

void testMajorityPartition(const std::vector<TestCase>& cases) {
std::cout << "=== Testing majorityPartition ===\n";
// Generic runner
template <typename Func>
void runTests(const std::string& title, const std::vector<TestCase>& cases, Func func) {
std::cout << "=== " << title << " ===\n";
for (auto& tc : cases) {
bool passed = false;
try {
auto copy = tc.arr; // partition modifies in-place
int result = majorityPartition(copy);
int result = func(tc.arr);
if (!tc.expectException && result == tc.expected) {
passed = true;
}
} catch (const std::invalid_argument&) {
if (tc.expectException) passed = true;
}
std::cout
<< tc.name
<< " -> " << (passed ? "PASS" : "FAIL")
<< "\n";
std::cout << tc.name << " -> " << (passed ? "PASS" : "FAIL") << "\n";
assert(passed);
}
std::cout << "\n";
}


int main() {
std::vector<TestCase> cases = {
{ "No majority", {1,2,3,4,5}, true, 0 },
Expand All @@ -151,8 +98,8 @@ int main() {
}(), false, 1 }
};

testMajorityCounting(cases);
testMajorityPartition(cases);
runTests("Testing majorityCounting (Boyer–Moore)", cases, majorityCounting);
runTests("Testing majorityFrequency (Hash Map)", cases, majorityFrequency);

std::cout << "All tests passed successfully!\n";
return 0;
Expand Down