Cleanup BoyerMoore (#4951)

* modify code to make use of java Optional class

* revert changes

* add java.util.Optional<Integer>

* add java.util.Optional

* refactors: make `findmajor` return `optional`

* refactors: make method name findMajor and split it

* refactors: change method name in tests

* Apply suggestions from code review

Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>

* change back to int

* fix: swap arguments

* tests: add some test cases

* refactor: add `isMajority` and avoid rounding

* style: use `var`

* style: swap arguments of `countOccurrences`

---------

Co-authored-by: vil02 <vil02@o2.pl>
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
This commit is contained in:
Prathamesh Powar 2023-10-31 13:37:59 +05:30 committed by GitHub
parent d086afce09
commit 574138c7a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 15 deletions

View File

@ -5,35 +5,50 @@ For more information on the algorithm refer
https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm
*/ */
package com.thealgorithms.others; package com.thealgorithms.others;
import java.util.Optional;
public final class BoyerMoore { public final class BoyerMoore {
private BoyerMoore() { private BoyerMoore() {
} }
public static int findmajor(final int[] a) { public static Optional<Integer> findMajor(final int[] a) {
final var candidate = findCandidate(a);
final var count = countOccurrences(candidate, a);
if (isMajority(count, a.length)) {
return Optional.of(candidate);
}
return Optional.empty();
}
private static int findCandidate(final int[] a) {
int count = 0; int count = 0;
int cand = -1; int candidate = -1;
for (final var k : a) { for (final var k : a) {
if (count == 0) { if (count == 0) {
cand = k; candidate = k;
count = 1; count = 1;
} else { } else {
if (k == cand) { if (k == candidate) {
count++; count++;
} else { } else {
count--; count--;
} }
} }
} }
count = 0; return candidate;
}
private static int countOccurrences(final int candidate, final int[] a) {
int count = 0;
for (final var j : a) { for (final var j : a) {
if (j == cand) { if (j == candidate) {
count++; count++;
} }
} }
if (count > (a.length / 2)) { return count;
return cand; }
}
return -1; private static boolean isMajority(final int count, final int totalCount) {
return 2 * count > totalCount;
} }
} }

View File

@ -11,12 +11,22 @@ import org.junit.jupiter.params.provider.MethodSource;
public class BoyerMooreTest { public class BoyerMooreTest {
@ParameterizedTest @ParameterizedTest
@MethodSource("inputStream") @MethodSource("inputStreamWithExistingMajority")
void numberTests(int expected, int[] input) { void checkWhenMajorityExists(int expected, int[] input) {
Assertions.assertEquals(expected, BoyerMoore.findmajor(input)); Assertions.assertEquals(expected, BoyerMoore.findMajor(input).get());
} }
private static Stream<Arguments> inputStream() { private static Stream<Arguments> inputStreamWithExistingMajority() {
return Stream.of(Arguments.of(5, new int[] {5, 5, 5, 2}), Arguments.of(10, new int[] {10, 10, 20}), Arguments.of(10, new int[] {10, 20, 10}), Arguments.of(10, new int[] {20, 10, 10}), Arguments.of(-1, new int[] {10, 10, 20, 20, 30, 30}), Arguments.of(4, new int[] {1, 4, 2, 4, 4, 5, 4})); return Stream.of(Arguments.of(5, new int[] {5, 5, 5, 2}), Arguments.of(10, new int[] {10, 10, 20}), Arguments.of(10, new int[] {10, 20, 10}), Arguments.of(10, new int[] {20, 10, 10}), Arguments.of(4, new int[] {1, 4, 2, 4, 4, 5, 4}), Arguments.of(-1, new int[] {-1}));
}
@ParameterizedTest
@MethodSource("inputStreamWithoutMajority")
void checkWhenMajorityExists(int[] input) {
Assertions.assertFalse(BoyerMoore.findMajor(input).isPresent());
}
private static Stream<Arguments> inputStreamWithoutMajority() {
return Stream.of(Arguments.of(new int[] {10, 10, 20, 20, 30, 30}), Arguments.of(new int[] {10, 20, 30, 40, 50}), Arguments.of(new int[] {1, 2}), Arguments.of(new int[] {}));
} }
} }