From adf21ab0c87bffd1c774072335a7d9d4f62fcee4 Mon Sep 17 00:00:00 2001 From: Hardik Pawar <97388607+Hardvan@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:18:48 +0530 Subject: [PATCH] feat: Add `CelebrityFinder` new algorithm with Junit tests (#5756) --- DIRECTORY.md | 2 + .../thealgorithms/stacks/CelebrityFinder.java | 52 +++++++++++++++++++ .../stacks/CelebrityFinderTest.java | 41 +++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 src/main/java/com/thealgorithms/stacks/CelebrityFinder.java create mode 100644 src/test/java/com/thealgorithms/stacks/CelebrityFinderTest.java diff --git a/DIRECTORY.md b/DIRECTORY.md index cb26c292b..11ce5b744 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -607,6 +607,7 @@ * [WiggleSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/WiggleSort.java) * stacks * [BalancedBrackets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/BalancedBrackets.java) + * [CelebrityFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/CelebrityFinder.java) * [DecimalToAnyUsingStack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/DecimalToAnyUsingStack.java) * [DuplicateBrackets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/DuplicateBrackets.java) * [InfixToPostfix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/InfixToPostfix.java) @@ -1163,6 +1164,7 @@ * [WiggleSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/WiggleSortTest.java) * stacks * [BalancedBracketsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/BalancedBracketsTest.java) + * [CelebrityFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/CelebrityFinderTest.java) * [DecimalToAnyUsingStackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/DecimalToAnyUsingStackTest.java) * [DuplicateBracketsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/DuplicateBracketsTest.java) * [InfixToPostfixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/InfixToPostfixTest.java) diff --git a/src/main/java/com/thealgorithms/stacks/CelebrityFinder.java b/src/main/java/com/thealgorithms/stacks/CelebrityFinder.java new file mode 100644 index 000000000..67ac861ef --- /dev/null +++ b/src/main/java/com/thealgorithms/stacks/CelebrityFinder.java @@ -0,0 +1,52 @@ +package com.thealgorithms.stacks; + +import java.util.Stack; + +/** + * Solves the celebrity problem using a stack-based algorithm. + * + *

Celebrity is someone known by everyone but doesn't know anyone else. + *

Applications: Graph theory and social network analysis. + * + * @author Hardvan + */ +public final class CelebrityFinder { + private CelebrityFinder() { + } + + /** + * Finds the celebrity in the given party matrix using a stack-based algorithm. + * + * @param party A 2D matrix where party[i][j] is 1 if i knows j, otherwise 0. + * @return The index of the celebrity, or -1 if there is no celebrity. + */ + public static int findCelebrity(int[][] party) { + + // Push all people onto the stack + Stack stack = new Stack<>(); + for (int i = 0; i < party.length; i++) { + stack.push(i); + } + + // Find the potential celebrity by comparing pairs + while (stack.size() > 1) { + int person1 = stack.pop(); + int person2 = stack.pop(); + + if (party[person1][person2] == 1) { + stack.push(person2); // person1 knows person2, so person2 might be the celebrity + } else { + stack.push(person1); // person1 doesn't know person2, so person1 might be the celebrity + } + } + + // Verify the candidate + int candidate = stack.pop(); + for (int i = 0; i < party.length; i++) { + if (i != candidate && (party[candidate][i] == 1 || party[i][candidate] == 0)) { + return -1; + } + } + return candidate; + } +} diff --git a/src/test/java/com/thealgorithms/stacks/CelebrityFinderTest.java b/src/test/java/com/thealgorithms/stacks/CelebrityFinderTest.java new file mode 100644 index 000000000..da0217940 --- /dev/null +++ b/src/test/java/com/thealgorithms/stacks/CelebrityFinderTest.java @@ -0,0 +1,41 @@ +package com.thealgorithms.stacks; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +public class CelebrityFinderTest { + + @ParameterizedTest + @MethodSource("providePartyMatrices") + public void testCelebrityFinder(int[][] party, int expected) { + assertEquals(expected, CelebrityFinder.findCelebrity(party)); + } + + private static Stream providePartyMatrices() { + return Stream.of( + // Test case 1: Celebrity exists + Arguments.of(new int[][] {{0, 1, 1}, {0, 0, 1}, {0, 0, 0}}, 2), + + // Test case 2: No celebrity + Arguments.of(new int[][] {{0, 1, 0}, {1, 0, 1}, {1, 1, 0}}, -1), + + // Test case 3: Everyone knows each other, no celebrity + Arguments.of(new int[][] {{0, 1, 1}, {1, 0, 1}, {1, 1, 0}}, -1), + + // Test case 4: Single person, they are trivially a celebrity + Arguments.of(new int[][] {{0}}, 0), + + // Test case 5: All know the last person, and they know no one + Arguments.of(new int[][] {{0, 1, 1, 1}, {0, 0, 1, 1}, {0, 0, 0, 1}, {0, 0, 0, 0}}, 3), + + // Test case 6: Larger party with no celebrity + Arguments.of(new int[][] {{0, 1, 1, 0}, {1, 0, 0, 1}, {0, 1, 0, 1}, {1, 1, 1, 0}}, -1), + + // Test case 7: Celebrity at the start of the matrix + Arguments.of(new int[][] {{0, 0, 0}, {1, 0, 1}, {1, 1, 0}}, 0)); + } +}