Skip to content

Commit ffb8a74

Browse files
authored
Merge branch 'master' into fibonacci_search_add_tests
2 parents 0c45239 + ca5fbbf commit ffb8a74

File tree

14 files changed

+592
-58
lines changed

14 files changed

+592
-58
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
uses: actions/setup-java@v4
1111
with:
1212
java-version: 21
13-
distribution: 'adopt'
13+
distribution: 'temurin'
1414
- name: Build with Maven
1515
run: mvn --batch-mode --update-snapshots verify
1616
- name: Upload coverage to codecov (tokenless)

.github/workflows/codeql.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
uses: actions/setup-java@v4
3131
with:
3232
java-version: 21
33-
distribution: 'adopt'
33+
distribution: 'temurin'
3434

3535
- name: Initialize CodeQL
3636
uses: github/codeql-action/init@v3

.github/workflows/infer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
uses: actions/setup-java@v4
1919
with:
2020
java-version: 21
21-
distribution: 'adopt'
21+
distribution: 'temurin'
2222

2323
- name: Set up OCaml
2424
uses: ocaml/setup-ocaml@v3

DIRECTORY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@
262262
* [LongestValidParentheses](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/LongestValidParentheses.java)
263263
* [MatrixChainMultiplication](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/MatrixChainMultiplication.java)
264264
* [MatrixChainRecursiveTopDownMemoisation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/MatrixChainRecursiveTopDownMemoisation.java)
265+
* [MaximumSumOfNonAdjacentElements](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/MaximumSumOfNonAdjacentElements.java)
265266
* [MinimumPathSum](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/MinimumPathSum.java)
266267
* [MinimumSumPartition](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/MinimumSumPartition.java)
267268
* [NewManShanksPrime](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/NewManShanksPrime.java)
@@ -815,12 +816,15 @@
815816
* [LongestPalindromicSubstringTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/LongestPalindromicSubstringTest.java)
816817
* [LongestValidParenthesesTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/LongestValidParenthesesTest.java)
817818
* [MatrixChainMultiplicationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/MatrixChainMultiplicationTest.java)
819+
* [MaximumSumOfNonAdjacentElementsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/MaximumSumOfNonAdjacentElementsTest.java)
818820
* [MinimumPathSumTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/MinimumPathSumTest.java)
819821
* [MinimumSumPartitionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/MinimumSumPartitionTest.java)
822+
* [NewManShanksPrimeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/NewManShanksPrimeTest.java)
820823
* [OptimalJobSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/OptimalJobSchedulingTest.java)
821824
* [PalindromicPartitioningTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/PalindromicPartitioningTest.java)
822825
* [PartitionProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/PartitionProblemTest.java)
823826
* [RegexMatchingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/RegexMatchingTest.java)
827+
* [RodCuttingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/RodCuttingTest.java)
824828
* [ShortestCommonSupersequenceLengthTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/ShortestCommonSupersequenceLengthTest.java)
825829
* [SubsetCountTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/SubsetCountTest.java)
826830
* [SubsetSumTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/SubsetSumTest.java)
@@ -829,6 +833,7 @@
829833
* [UniquePathsTests](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/UniquePathsTests.java)
830834
* [UniqueSubsequencesCountTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/UniqueSubsequencesCountTest.java)
831835
* [WildcardMatchingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/WildcardMatchingTest.java)
836+
* [WineProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/WineProblemTest.java)
832837
* geometry
833838
* [GrahamScanTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/GrahamScanTest.java)
834839
* greedyalgorithms
@@ -992,6 +997,7 @@
992997
* [SRTFSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/SRTFSchedulingTest.java)
993998
* searches
994999
* [BinarySearch2dArrayTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/BinarySearch2dArrayTest.java)
1000+
* [BinarySearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/BinarySearchTest.java)
9951001
* [BM25InvertedIndexTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/BM25InvertedIndexTest.java)
9961002
* [BreadthFirstSearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/BreadthFirstSearchTest.java)
9971003
* [DepthFirstSearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/DepthFirstSearchTest.java)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.thealgorithms.dynamicprogramming;
2+
3+
/**
4+
* Class to find the maximum sum of non-adjacent elements in an array. This
5+
* class contains two approaches: one with O(n) space complexity and another
6+
* with O(1) space optimization. For more information, refer to
7+
* https://takeuforward.org/data-structure/maximum-sum-of-non-adjacent-elements-dp-5/
8+
*/
9+
final class MaximumSumOfNonAdjacentElements {
10+
11+
private MaximumSumOfNonAdjacentElements() {
12+
}
13+
14+
/**
15+
* Approach 1: Uses a dynamic programming array to store the maximum sum at
16+
* each index. Time Complexity: O(n) - where n is the length of the input
17+
* array. Space Complexity: O(n) - due to the additional dp array.
18+
* @param arr The input array of integers.
19+
* @return The maximum sum of non-adjacent elements.
20+
*/
21+
public static int getMaxSumApproach1(int[] arr) {
22+
if (arr.length == 0) {
23+
return 0; // Check for empty array
24+
}
25+
26+
int n = arr.length;
27+
int[] dp = new int[n];
28+
29+
// Base case: Maximum sum if only one element is present.
30+
dp[0] = arr[0];
31+
32+
for (int ind = 1; ind < n; ind++) {
33+
34+
// Case 1: Do not take the current element, carry forward the previous max
35+
// sum.
36+
int notTake = dp[ind - 1];
37+
38+
// Case 2: Take the current element, add it to the max sum up to two
39+
// indices before.
40+
int take = arr[ind];
41+
if (ind > 1) {
42+
take += dp[ind - 2];
43+
}
44+
45+
// Store the maximum of both choices in the dp array.
46+
dp[ind] = Math.max(take, notTake);
47+
}
48+
49+
return dp[n - 1];
50+
}
51+
52+
/**
53+
* Approach 2: Optimized space complexity approach using two variables instead
54+
* of an array. Time Complexity: O(n) - where n is the length of the input
55+
* array. Space Complexity: O(1) - as it only uses constant space for two
56+
* variables.
57+
* @param arr The input array of integers.
58+
* @return The maximum sum of non-adjacent elements.
59+
*/
60+
public static int getMaxSumApproach2(int[] arr) {
61+
if (arr.length == 0) {
62+
return 0; // Check for empty array
63+
}
64+
65+
int n = arr.length;
66+
67+
// Two variables to keep track of previous two results:
68+
// prev1 = max sum up to the last element (n-1)
69+
// prev2 = max sum up to the element before last (n-2)
70+
71+
int prev1 = arr[0]; // Base case: Maximum sum for the first element.
72+
int prev2 = 0;
73+
74+
for (int ind = 1; ind < n; ind++) {
75+
// Case 1: Do not take the current element, keep the last max sum.
76+
int notTake = prev1;
77+
78+
// Case 2: Take the current element and add it to the result from two
79+
// steps back.
80+
int take = arr[ind];
81+
if (ind > 1) {
82+
take += prev2;
83+
}
84+
85+
// Calculate the current maximum sum and update previous values.
86+
int current = Math.max(take, notTake);
87+
88+
// Shift prev1 and prev2 for the next iteration.
89+
prev2 = prev1;
90+
prev1 = current;
91+
}
92+
93+
return prev1;
94+
}
95+
}
Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,48 @@
11
package com.thealgorithms.dynamicprogramming;
22

33
/**
4+
* The NewManShanksPrime class provides a method to determine whether the nth
5+
* New Man Shanks prime matches an expected answer.
6+
*
7+
* <p>This is based on the New Man Shanks prime sequence defined by the recurrence
8+
* relation:</p>
9+
*
10+
* <pre>
11+
* a(n) = 2 * a(n-1) + a(n-2) for n >= 2
12+
* a(0) = 1
13+
* a(1) = 1
14+
* </pre>
15+
*
16+
* <p>For more information on New Man Shanks primes, please refer to the
17+
* <a href="https://en.wikipedia.org/wiki/Newman%E2%80%93Shanks%E2%80%93Williams_prime">
18+
* Wikipedia article</a>.</p>
19+
*
20+
* <p>Note: The class is designed to be non-instantiable.</p>
21+
*
422
* @author <a href="https://github.com/siddhant2002">Siddhant Swarup Mallick</a>
5-
* Program description - To find the New Man Shanks Prime.
6-
* <a href="https://en.wikipedia.org/wiki/Newman%E2%80%93Shanks%E2%80%93Williams_prime">Wikipedia</a>
723
*/
824
public final class NewManShanksPrime {
925
private NewManShanksPrime() {
1026
}
1127

28+
/**
29+
* Calculates the nth New Man Shanks prime and checks if it equals the
30+
* expected answer.
31+
*
32+
* @param n the index of the New Man Shanks prime to calculate (0-based).
33+
* @param expectedAnswer the expected value of the nth New Man Shanks prime.
34+
* @return true if the calculated nth New Man Shanks prime matches the
35+
* expected answer; false otherwise.
36+
*/
1237
public static boolean nthManShanksPrime(int n, int expectedAnswer) {
1338
int[] a = new int[n + 1];
14-
// array of n+1 size is initialized
1539
a[0] = 1;
1640
a[1] = 1;
17-
// The 0th and 1st index position values are fixed. They are initialized as 1
41+
1842
for (int i = 2; i <= n; i++) {
1943
a[i] = 2 * a[i - 1] + a[i - 2];
2044
}
21-
// The loop is continued till n
45+
2246
return a[n] == expectedAnswer;
23-
// returns true if calculated answer matches with expected answer
2447
}
2548
}

src/main/java/com/thealgorithms/dynamicprogramming/RodCutting.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ private RodCutting() {
1515
* @param price An array representing the prices of different pieces, where price[i-1]
1616
* represents the price of a piece of length i.
1717
* @param n The length of the rod to be cut.
18+
* @throws IllegalArgumentException if the price array is null or empty, or if n is less than 0.
1819
* @return The maximum obtainable value.
1920
*/
2021
public static int cutRod(int[] price, int n) {
22+
if (price == null || price.length == 0) {
23+
throw new IllegalArgumentException("Price array cannot be null or empty.");
24+
}
2125
// Create an array to store the maximum obtainable values for each rod length.
2226
int[] val = new int[n + 1];
2327
val[0] = 0;

src/main/java/com/thealgorithms/dynamicprogramming/WineProblem.java

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,40 @@
11
package com.thealgorithms.dynamicprogramming;
22

33
/**
4-
* Imagine you have a collection of N wines placed next to each other on the
5-
* shelf. The price of ith wine is pi(Prices of different wines are different).
6-
* Because wine gets better every year supposing today is year 1, on year y the
7-
* price would be y*pi i.e y times the value of the initial year. You want to
8-
* sell all wines but you have to sell one wine per year. One more constraint on
9-
* each year you are allowed to sell either leftmost or rightmost wine on the
10-
* shelf. You are not allowed to reorder. You have to find the maximum profit
4+
* The WineProblem class provides a solution to the wine selling problem.
5+
* Given a collection of N wines with different prices, the objective is to maximize profit by selling
6+
* one wine each year, considering the constraint that only the leftmost or rightmost wine can be sold
7+
* at any given time.
118
*
9+
* The price of the ith wine is pi, and the selling price increases by a factor of the year in which
10+
* it is sold. This class implements three approaches to solve the problem:
11+
*
12+
* 1. **Recursion**: A straightforward recursive method that computes the maximum profit.
13+
* - Time Complexity: O(2^N)
14+
* - Space Complexity: O(N) due to recursive calls.
15+
*
16+
* 2. **Top-Down Dynamic Programming (Memoization)**: This approach caches the results of subproblems
17+
* to avoid redundant computations.
18+
* - Time Complexity: O(N^2)
19+
* - Space Complexity: O(N^2) for the storage of results and O(N) for recursion stack.
20+
*
21+
* 3. **Bottom-Up Dynamic Programming (Tabulation)**: This method builds a table iteratively to
22+
* compute the maximum profit for all possible subproblems.
23+
* - Time Complexity: O(N^2)
24+
* - Space Complexity: O(N^2) for the table.
1225
*/
1326
public final class WineProblem {
1427
private WineProblem() {
1528
}
1629

17-
// Method 1: Using Recursion
18-
// Time Complexity=0(2^N) Space Complexity=Recursion extra space
30+
/**
31+
* Calculate maximum profit using recursion.
32+
*
33+
* @param arr Array of wine prices.
34+
* @param si Start index of the wine to consider.
35+
* @param ei End index of the wine to consider.
36+
* @return Maximum profit obtainable by selling the wines.
37+
*/
1938
public static int wpRecursion(int[] arr, int si, int ei) {
2039
int n = arr.length;
2140
int year = (n - (ei - si + 1)) + 1;
@@ -29,8 +48,15 @@ public static int wpRecursion(int[] arr, int si, int ei) {
2948
return Math.max(start, end);
3049
}
3150

32-
// Method 2: Top-Down DP(Memoization)
33-
// Time Complexity=0(N*N) Space Complexity=0(N*N)+Recursion extra space
51+
/**
52+
* Calculate maximum profit using top-down dynamic programming with memoization.
53+
*
54+
* @param arr Array of wine prices.
55+
* @param si Start index of the wine to consider.
56+
* @param ei End index of the wine to consider.
57+
* @param strg 2D array to store results of subproblems.
58+
* @return Maximum profit obtainable by selling the wines.
59+
*/
3460
public static int wptd(int[] arr, int si, int ei, int[][] strg) {
3561
int n = arr.length;
3662
int year = (n - (ei - si + 1)) + 1;
@@ -45,15 +71,22 @@ public static int wptd(int[] arr, int si, int ei, int[][] strg) {
4571
int end = wptd(arr, si, ei - 1, strg) + arr[ei] * year;
4672

4773
int ans = Math.max(start, end);
48-
4974
strg[si][ei] = ans;
5075

5176
return ans;
5277
}
5378

54-
// Method 3: Bottom-Up DP(Tabulation)
55-
// Time Complexity=0(N*N/2)->0(N*N) Space Complexity=0(N*N)
79+
/**
80+
* Calculate maximum profit using bottom-up dynamic programming with tabulation.
81+
*
82+
* @param arr Array of wine prices.
83+
* @throws IllegalArgumentException if the input array is null or empty.
84+
* @return Maximum profit obtainable by selling the wines.
85+
*/
5686
public static int wpbu(int[] arr) {
87+
if (arr == null || arr.length == 0) {
88+
throw new IllegalArgumentException("Input array cannot be null or empty.");
89+
}
5790
int n = arr.length;
5891
int[][] strg = new int[n][n];
5992

@@ -73,13 +106,4 @@ public static int wpbu(int[] arr) {
73106
}
74107
return strg[0][n - 1];
75108
}
76-
77-
public static void main(String[] args) {
78-
int[] arr = {2, 3, 5, 1, 4};
79-
System.out.println("Method 1: " + wpRecursion(arr, 0, arr.length - 1));
80-
System.out.println("Method 2: " + wptd(arr, 0, arr.length - 1, new int[arr.length][arr.length]));
81-
System.out.println("Method 3: " + wpbu(arr));
82-
}
83109
}
84-
// Memoization vs Tabulation : https://www.geeksforgeeks.org/tabulation-vs-memoization/
85-
// Question Link : https://www.geeksforgeeks.org/maximum-profit-sale-wines/

src/main/java/com/thealgorithms/searches/BinarySearch.java

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
package com.thealgorithms.searches;
22

33
import com.thealgorithms.devutils.searches.SearchAlgorithm;
4-
import java.util.Arrays;
5-
import java.util.Random;
6-
import java.util.concurrent.ThreadLocalRandom;
7-
import java.util.stream.IntStream;
84

95
/**
106
* Binary search is one of the most popular algorithms The algorithm finds the
@@ -57,26 +53,4 @@ private <T extends Comparable<T>> int search(T[] array, T key, int left, int rig
5753
return search(array, key, median + 1, right);
5854
}
5955
}
60-
61-
// Driver Program
62-
public static void main(String[] args) {
63-
// Just generate data
64-
Random r = ThreadLocalRandom.current();
65-
66-
int size = 100;
67-
int maxElement = 100000;
68-
69-
Integer[] integers = IntStream.generate(() -> r.nextInt(maxElement)).limit(size).sorted().boxed().toArray(Integer[] ::new);
70-
71-
// The element that should be found
72-
int shouldBeFound = integers[r.nextInt(size - 1)];
73-
74-
BinarySearch search = new BinarySearch();
75-
int atIndex = search.find(integers, shouldBeFound);
76-
77-
System.out.printf("Should be found: %d. Found %d at index %d. An array length %d%n", shouldBeFound, integers[atIndex], atIndex, size);
78-
79-
int toCheck = Arrays.binarySearch(integers, shouldBeFound);
80-
System.out.printf("Found by system method at an index: %d. Is equal: %b%n", toCheck, toCheck == atIndex);
81-
}
8256
}

0 commit comments

Comments
 (0)