Skip to content

Commit bb5dc41

Browse files
authored
Merge branch 'master' into SMJI/stack/min_max_const_time
2 parents b0da2ec + be70801 commit bb5dc41

File tree

9 files changed

+344
-10
lines changed

9 files changed

+344
-10
lines changed

DIRECTORY.md

+4
Original file line numberDiff line numberDiff line change
@@ -607,13 +607,15 @@
607607
* [WiggleSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/WiggleSort.java)
608608
* stacks
609609
* [BalancedBrackets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/BalancedBrackets.java)
610+
* [CelebrityFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/CelebrityFinder.java)
610611
* [DecimalToAnyUsingStack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/DecimalToAnyUsingStack.java)
611612
* [DuplicateBrackets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/DuplicateBrackets.java)
612613
* [InfixToPostfix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/InfixToPostfix.java)
613614
* [InfixToPrefix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/InfixToPrefix.java)
614615
* [LargestRectangle](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/LargestRectangle.java)
615616
* [MaximumMinimumWindow](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/MaximumMinimumWindow.java)
616617
* [MinStackUsingSingleStack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/MinStackUsingSingleStack.java)
618+
* [MinStackUsingTwoStacks](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/MinStackUsingTwoStacks.java)
617619
* [NextGreaterElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextGreaterElement.java)
618620
* [NextSmallerElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextSmallerElement.java)
619621
* [PostfixEvaluator](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/PostfixEvaluator.java)
@@ -1162,12 +1164,14 @@
11621164
* [WiggleSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/WiggleSortTest.java)
11631165
* stacks
11641166
* [BalancedBracketsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/BalancedBracketsTest.java)
1167+
* [CelebrityFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/CelebrityFinderTest.java)
11651168
* [DecimalToAnyUsingStackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/DecimalToAnyUsingStackTest.java)
11661169
* [DuplicateBracketsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/DuplicateBracketsTest.java)
11671170
* [InfixToPostfixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/InfixToPostfixTest.java)
11681171
* [InfixToPrefixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/InfixToPrefixTest.java)
11691172
* [LargestRectangleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/LargestRectangleTest.java)
11701173
* [MinStackUsingSingleStackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/MinStackUsingSingleStackTest.java)
1174+
* [MinStackUsingTwoStacksTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/MinStackUsingTwoStacksTest.java)
11711175
* [NextGreaterElementTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/NextGreaterElementTest.java)
11721176
* [NextSmallerElementTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/NextSmallerElementTest.java)
11731177
* [PostfixEvaluatorTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/PostfixEvaluatorTest.java)

src/main/java/com/thealgorithms/backtracking/ArrayCombination.java

+20-8
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,44 @@
44
import java.util.List;
55

66
/**
7-
* Finds all combinations of 0...n-1 of length k
7+
* This class provides methods to find all combinations of integers from 0 to n-1
8+
* of a specified length k using backtracking.
89
*/
910
public final class ArrayCombination {
1011
private ArrayCombination() {
1112
}
1213

1314
/**
14-
* Finds all combinations of length k of 0..n-1 using backtracking.
15+
* Generates all possible combinations of length k from the integers 0 to n-1.
1516
*
16-
* @param n Number of the elements.
17-
* @param k Length of the combination.
18-
* @return A list of all combinations of length k.
17+
* @param n The total number of elements (0 to n-1).
18+
* @param k The desired length of each combination.
19+
* @return A list containing all combinations of length k.
20+
* @throws IllegalArgumentException if n or k are negative, or if k is greater than n.
1921
*/
2022
public static List<List<Integer>> combination(int n, int k) {
2123
if (n < 0 || k < 0 || k > n) {
22-
throw new IllegalArgumentException("Wrong input.");
24+
throw new IllegalArgumentException("Invalid input: n must be non-negative, k must be non-negative and less than or equal to n.");
2325
}
2426

2527
List<List<Integer>> combinations = new ArrayList<>();
2628
combine(combinations, new ArrayList<>(), 0, n, k);
2729
return combinations;
2830
}
2931

32+
/**
33+
* A helper method that uses backtracking to find combinations.
34+
*
35+
* @param combinations The list to store all valid combinations found.
36+
* @param current The current combination being built.
37+
* @param start The starting index for the current recursion.
38+
* @param n The total number of elements (0 to n-1).
39+
* @param k The desired length of each combination.
40+
*/
3041
private static void combine(List<List<Integer>> combinations, List<Integer> current, int start, int n, int k) {
31-
if (current.size() == k) { // Base case: combination found
32-
combinations.add(new ArrayList<>(current)); // Copy to avoid modification
42+
// Base case: combination found
43+
if (current.size() == k) {
44+
combinations.add(new ArrayList<>(current));
3345
return;
3446
}
3547

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.thealgorithms.geometry;
2+
3+
import java.awt.Point;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
7+
/**
8+
* The {@code BresenhamLine} class implements the Bresenham's line algorithm,
9+
* which is an efficient way to determine the points of a straight line
10+
* between two given points in a 2D space.
11+
*
12+
* <p>This algorithm uses integer arithmetic to calculate the points,
13+
* making it suitable for rasterization in computer graphics.</p>
14+
*
15+
* For more information, please visit {@link https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm}
16+
*/
17+
public final class BresenhamLine {
18+
19+
private BresenhamLine() {
20+
// Private constructor to prevent instantiation.
21+
}
22+
23+
/**
24+
* Finds the list of points that form a straight line between two endpoints.
25+
*
26+
* @param x0 the x-coordinate of the starting point
27+
* @param y0 the y-coordinate of the starting point
28+
* @param x1 the x-coordinate of the ending point
29+
* @param y1 the y-coordinate of the ending point
30+
* @return a {@code List<Point>} containing all points on the line
31+
*/
32+
public static List<Point> findLine(int x0, int y0, int x1, int y1) {
33+
List<Point> line = new ArrayList<>();
34+
35+
// Calculate differences and steps for each axis
36+
int dx = Math.abs(x1 - x0); // Change in x
37+
int dy = Math.abs(y1 - y0); // Change in y
38+
int sx = (x0 < x1) ? 1 : -1; // Step in x direction
39+
int sy = (y0 < y1) ? 1 : -1; // Step in y direction
40+
int err = dx - dy; // Initial error term
41+
42+
// Loop until we reach the endpoint
43+
while (true) {
44+
line.add(new Point(x0, y0)); // Add current point to the line
45+
46+
// Check if we've reached the endpoint
47+
if (x0 == x1 && y0 == y1) {
48+
break; // Exit loop if endpoint is reached
49+
}
50+
51+
// Calculate error term doubled for decision making
52+
final int e2 = err * 2;
53+
54+
// Adjust x coordinate if necessary
55+
if (e2 > -dy) {
56+
err -= dy; // Update error term
57+
x0 += sx; // Move to next point in x direction
58+
}
59+
60+
// Adjust y coordinate if necessary
61+
if (e2 < dx) {
62+
err += dx; // Update error term
63+
y0 += sy; // Move to next point in y direction
64+
}
65+
}
66+
67+
return line; // Return the list of points forming the line
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.thealgorithms.stacks;
2+
3+
import java.util.Stack;
4+
5+
/**
6+
* Solves the celebrity problem using a stack-based algorithm.
7+
*
8+
* <p>Celebrity is someone known by everyone but doesn't know anyone else.
9+
* <p>Applications: Graph theory and social network analysis.
10+
*
11+
* @author Hardvan
12+
*/
13+
public final class CelebrityFinder {
14+
private CelebrityFinder() {
15+
}
16+
17+
/**
18+
* Finds the celebrity in the given party matrix using a stack-based algorithm.
19+
*
20+
* @param party A 2D matrix where party[i][j] is 1 if i knows j, otherwise 0.
21+
* @return The index of the celebrity, or -1 if there is no celebrity.
22+
*/
23+
public static int findCelebrity(int[][] party) {
24+
25+
// Push all people onto the stack
26+
Stack<Integer> stack = new Stack<>();
27+
for (int i = 0; i < party.length; i++) {
28+
stack.push(i);
29+
}
30+
31+
// Find the potential celebrity by comparing pairs
32+
while (stack.size() > 1) {
33+
int person1 = stack.pop();
34+
int person2 = stack.pop();
35+
36+
if (party[person1][person2] == 1) {
37+
stack.push(person2); // person1 knows person2, so person2 might be the celebrity
38+
} else {
39+
stack.push(person1); // person1 doesn't know person2, so person1 might be the celebrity
40+
}
41+
}
42+
43+
// Verify the candidate
44+
int candidate = stack.pop();
45+
for (int i = 0; i < party.length; i++) {
46+
if (i != candidate && (party[candidate][i] == 1 || party[i][candidate] == 0)) {
47+
return -1;
48+
}
49+
}
50+
return candidate;
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.thealgorithms.stacks;
2+
3+
import java.util.Stack;
4+
5+
/**
6+
* Min-Stack implementation that supports push, pop, and retrieving the minimum element in constant time.
7+
*
8+
* @author Hardvan
9+
*/
10+
public final class MinStackUsingTwoStacks {
11+
MinStackUsingTwoStacks() {
12+
}
13+
14+
private final Stack<Integer> stack = new Stack<>();
15+
private final Stack<Integer> minStack = new Stack<>();
16+
17+
/**
18+
* Pushes a new element onto the {@code stack}.
19+
* If the value is less than or equal to the current minimum, it is also pushed onto the {@code minStack}.
20+
*
21+
* @param value The value to be pushed.
22+
*/
23+
public void push(int value) {
24+
stack.push(value);
25+
if (minStack.isEmpty() || value <= minStack.peek()) {
26+
minStack.push(value);
27+
}
28+
}
29+
30+
/**
31+
* Removes the top element from the stack.
32+
* If the element is the minimum element, it is also removed from the {@code minStack}.
33+
*/
34+
public void pop() {
35+
if (stack.pop().equals(minStack.peek())) {
36+
minStack.pop();
37+
}
38+
}
39+
40+
/**
41+
* Retrieves the top element of the stack.
42+
*
43+
* @return The top element.
44+
*/
45+
public int top() {
46+
return stack.peek();
47+
}
48+
49+
/**
50+
* Retrieves the minimum element in the stack.
51+
*
52+
* @return The minimum element.
53+
*/
54+
public int getMin() {
55+
return minStack.peek();
56+
}
57+
}

src/test/java/com/thealgorithms/backtracking/ArrayCombinationTest.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,14 @@ void testCombinationThrows(int n, int k) {
2727

2828
private static Stream<Arguments> regularInputs() {
2929
return Stream.of(Arguments.of(0, 0, List.of(new ArrayList<Integer>())), Arguments.of(1, 0, List.of(new ArrayList<Integer>())), Arguments.of(1, 1, List.of(List.of(0))), Arguments.of(3, 0, List.of(new ArrayList<Integer>())), Arguments.of(3, 1, List.of(List.of(0), List.of(1), List.of(2))),
30-
Arguments.of(4, 2, List.of(List.of(0, 1), List.of(0, 2), List.of(0, 3), List.of(1, 2), List.of(1, 3), List.of(2, 3))));
30+
Arguments.of(4, 2, List.of(List.of(0, 1), List.of(0, 2), List.of(0, 3), List.of(1, 2), List.of(1, 3), List.of(2, 3))),
31+
Arguments.of(5, 3, List.of(List.of(0, 1, 2), List.of(0, 1, 3), List.of(0, 1, 4), List.of(0, 2, 3), List.of(0, 2, 4), List.of(0, 3, 4), List.of(1, 2, 3), List.of(1, 2, 4), List.of(1, 3, 4), List.of(2, 3, 4))),
32+
Arguments.of(6, 4,
33+
List.of(List.of(0, 1, 2, 3), List.of(0, 1, 2, 4), List.of(0, 1, 2, 5), List.of(0, 1, 3, 4), List.of(0, 1, 3, 5), List.of(0, 1, 4, 5), List.of(0, 2, 3, 4), List.of(0, 2, 3, 5), List.of(0, 2, 4, 5), List.of(0, 3, 4, 5), List.of(1, 2, 3, 4), List.of(1, 2, 3, 5), List.of(1, 2, 4, 5),
34+
List.of(1, 3, 4, 5), List.of(2, 3, 4, 5))));
3135
}
3236

3337
private static Stream<Arguments> wrongInputs() {
34-
return Stream.of(Arguments.of(-1, 0), Arguments.of(0, -1), Arguments.of(2, 100));
38+
return Stream.of(Arguments.of(-1, 0), Arguments.of(0, -1), Arguments.of(2, 100), Arguments.of(3, 4));
3539
}
3640
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.thealgorithms.geometry;
2+
3+
import java.awt.Point;
4+
import java.util.Collection;
5+
import java.util.List;
6+
import java.util.stream.Stream;
7+
import org.junit.jupiter.api.Assertions;
8+
import org.junit.jupiter.params.ParameterizedTest;
9+
import org.junit.jupiter.params.provider.Arguments;
10+
import org.junit.jupiter.params.provider.MethodSource;
11+
12+
/**
13+
* The {@code BresenhamLineTest} class contains unit tests for the
14+
* {@code BresenhamLine} class, specifically testing the
15+
* {@code findLine} method.
16+
*
17+
* <p>This class uses parameterized tests to validate the output of
18+
* Bresenham's line algorithm for various input points.</p>
19+
*/
20+
class BresenhamLineTest {
21+
22+
/**
23+
* Provides test cases for the parameterized test.
24+
*
25+
* <p>Each test case includes starting coordinates, ending coordinates,
26+
* and the expected collection of points that should be generated by the
27+
* {@code findLine} method.</p>
28+
*
29+
* @return a stream of arguments containing test cases
30+
*/
31+
static Stream<Arguments> linePointsProvider() {
32+
return Stream.of(Arguments.of(0, 0, 5, 5, List.of(new Point(0, 0), new Point(1, 1), new Point(2, 2), new Point(3, 3), new Point(4, 4), new Point(5, 5))), Arguments.of(0, 0, 5, 0, List.of(new Point(0, 0), new Point(1, 0), new Point(2, 0), new Point(3, 0), new Point(4, 0), new Point(5, 0))),
33+
Arguments.of(0, 0, 0, 5, List.of(new Point(0, 0), new Point(0, 1), new Point(0, 2), new Point(0, 3), new Point(0, 4), new Point(0, 5))), Arguments.of(-2, -2, -5, -5, List.of(new Point(-2, -2), new Point(-3, -3), new Point(-4, -4), new Point(-5, -5))),
34+
Arguments.of(-1, -1, 2, 2, List.of(new Point(-1, -1), new Point(0, 0), new Point(1, 1), new Point(2, 2))), Arguments.of(2, -1, -1, -4, List.of(new Point(2, -1), new Point(1, -2), new Point(0, -3), new Point(-1, -4))));
35+
}
36+
37+
/**
38+
* Tests the {@code findLine} method of the {@code BresenhamLine} class.
39+
*
40+
* <p>This parameterized test runs multiple times with different sets of
41+
* starting and ending coordinates to validate that the generated points
42+
* match the expected output.</p>
43+
*
44+
* @param x0 the x-coordinate of the starting point
45+
* @param y0 the y-coordinate of the starting point
46+
* @param x1 the x-coordinate of the ending point
47+
* @param y1 the y-coordinate of the ending point
48+
* @param expected a collection of expected points that should form a line
49+
*/
50+
@ParameterizedTest
51+
@MethodSource("linePointsProvider")
52+
void testFindLine(int x0, int y0, int x1, int y1, Collection<Point> expected) {
53+
List<Point> actual = BresenhamLine.findLine(x0, y0, x1, y1);
54+
Assertions.assertEquals(expected.size(), actual.size(), "The size of the points list should match.");
55+
Assertions.assertTrue(expected.containsAll(actual) && actual.containsAll(expected), "The points generated should match the expected points.");
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.thealgorithms.stacks;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import java.util.stream.Stream;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.Arguments;
8+
import org.junit.jupiter.params.provider.MethodSource;
9+
10+
public class CelebrityFinderTest {
11+
12+
@ParameterizedTest
13+
@MethodSource("providePartyMatrices")
14+
public void testCelebrityFinder(int[][] party, int expected) {
15+
assertEquals(expected, CelebrityFinder.findCelebrity(party));
16+
}
17+
18+
private static Stream<Arguments> providePartyMatrices() {
19+
return Stream.of(
20+
// Test case 1: Celebrity exists
21+
Arguments.of(new int[][] {{0, 1, 1}, {0, 0, 1}, {0, 0, 0}}, 2),
22+
23+
// Test case 2: No celebrity
24+
Arguments.of(new int[][] {{0, 1, 0}, {1, 0, 1}, {1, 1, 0}}, -1),
25+
26+
// Test case 3: Everyone knows each other, no celebrity
27+
Arguments.of(new int[][] {{0, 1, 1}, {1, 0, 1}, {1, 1, 0}}, -1),
28+
29+
// Test case 4: Single person, they are trivially a celebrity
30+
Arguments.of(new int[][] {{0}}, 0),
31+
32+
// Test case 5: All know the last person, and they know no one
33+
Arguments.of(new int[][] {{0, 1, 1, 1}, {0, 0, 1, 1}, {0, 0, 0, 1}, {0, 0, 0, 0}}, 3),
34+
35+
// Test case 6: Larger party with no celebrity
36+
Arguments.of(new int[][] {{0, 1, 1, 0}, {1, 0, 0, 1}, {0, 1, 0, 1}, {1, 1, 1, 0}}, -1),
37+
38+
// Test case 7: Celebrity at the start of the matrix
39+
Arguments.of(new int[][] {{0, 0, 0}, {1, 0, 1}, {1, 1, 0}}, 0));
40+
}
41+
}

0 commit comments

Comments
 (0)