diff --git a/Algorithms.Tests/Other/BoyerMooreMajorityVoteTests.cs b/Algorithms.Tests/Other/BoyerMooreMajorityVoteTests.cs new file mode 100644 index 00000000..90fb74dd --- /dev/null +++ b/Algorithms.Tests/Other/BoyerMooreMajorityVoteTests.cs @@ -0,0 +1,88 @@ +using Algorithms.Other; +using NUnit.Framework; +using FluentAssertions; + +namespace Algorithms.Tests.Other; + +public class BoyerMooreMajorityVoteTests +{ + [Test] + public void FindMajority_SimpleMajority_ReturnsCorrectElement() + { + var nums = new[] { 3, 3, 4, 2, 3, 3, 3 }; + var result = BoyerMooreMajorityVote.FindMajority(nums); + result.Should().Be(3); + } + + [Test] + public void FindMajority_AllSameElements_ReturnsThatElement() + { + var nums = new[] { 5, 5, 5, 5 }; + var result = BoyerMooreMajorityVote.FindMajority(nums); + result.Should().Be(5); + } + + [Test] + public void FindMajority_NoMajority_ReturnsNull() + { + var nums = new[] { 1, 2, 3, 4 }; + var result = BoyerMooreMajorityVote.FindMajority(nums); + result.Should().BeNull(); + } + + [Test] + public void FindMajority_EmptyArray_ReturnsNull() + { + var nums = Array.Empty(); + var result = BoyerMooreMajorityVote.FindMajority(nums); + result.Should().BeNull(); + } + + [Test] + public void FindMajority_NullArray_ReturnsNull() + { + int[]? nums = null; + var result = BoyerMooreMajorityVote.FindMajority(nums!); + result.Should().BeNull(); + } + + [Test] + public void FindMajority_SingleElement_ReturnsThatElement() + { + var nums = new[] { 7 }; + var result = BoyerMooreMajorityVote.FindMajority(nums); + result.Should().Be(7); + } + + [Test] + public void FindMajority_MajorityAtEnd_ReturnsCorrectElement() + { + var nums = new[] { 1, 2, 2, 2, 2 }; + var result = BoyerMooreMajorityVote.FindMajority(nums); + result.Should().Be(2); + } + + [Test] + public void FindMajority_MajorityAtStart_ReturnsCorrectElement() + { + var nums = new[] { 8, 8, 8, 8, 1, 2 }; + var result = BoyerMooreMajorityVote.FindMajority(nums); + result.Should().Be(8); + } + + [Test] + public void FindMajority_NegativeNumbers_ReturnsCorrectElement() + { + var nums = new[] { -1, -1, -1, 2, 2 }; + var result = BoyerMooreMajorityVote.FindMajority(nums); + result.Should().Be(-1); + } + + [Test] + public void FindMajority_ExactlyHalf_ReturnsNull() + { + var nums = new[] { 1, 1, 2, 2 }; + var result = BoyerMooreMajorityVote.FindMajority(nums); + result.Should().BeNull(); + } +} diff --git a/Algorithms/Other/BoyerMooreMajorityVote.cs b/Algorithms/Other/BoyerMooreMajorityVote.cs new file mode 100644 index 00000000..6c3ba77e --- /dev/null +++ b/Algorithms/Other/BoyerMooreMajorityVote.cs @@ -0,0 +1,45 @@ +namespace Algorithms.Other; + +/// +/// Boyer-Moore Majority Vote algorithm. +/// Finds element appearing more than n/2 times in O(n) time, O(1) space. +/// +public static class BoyerMooreMajorityVote +{ + /// + /// Finds the majority element. + /// + /// Input array. + /// Majority element or null. + public static int? FindMajority(int[] nums) + { + if (nums == null || nums.Length == 0) + { + return null; + } + + var candidate = FindCandidate(nums); + return IsMajority(nums, candidate) ? candidate : null; + } + + private static int FindCandidate(int[] nums) + { + int candidate = nums[0]; + int count = 1; + + for (int i = 1; i < nums.Length; i++) + { + if (count == 0) + { + candidate = nums[i]; + } + + count += nums[i] == candidate ? 1 : -1; + } + + return candidate; + } + + private static bool IsMajority(int[] nums, int candidate) => + nums.Count(n => n == candidate) > nums.Length / 2; +}