Change project structure to a Maven Java project + Refactor (#2816)

This commit is contained in:
Aitor Fidalgo Sánchez
2021-11-12 07:59:36 +01:00
committed by GitHub
parent 8e533d2617
commit 9fb3364ccc
642 changed files with 26570 additions and 25488 deletions

View File

@ -0,0 +1,83 @@
package com.thealgorithms.dynamicprogramming;
/*
* this is an important Algo in which
* we have starting and ending of board and we have to reach
* we have to count no. of ways
* that help to reach end point i.e number by rolling dice
* which have 1 to 6 digits
Test Case:
here target is 10
int n=10;
startAlgo();
System.out.println(bpR(0,n));
System.out.println(endAlgo()+"ms");
int[] strg=new int [n+1];
startAlgo();
System.out.println(bpRS(0,n,strg));
System.out.println(endAlgo()+"ms");
startAlgo();
System.out.println(bpIS(0,n,strg));
System.out.println(endAlgo()+"ms");
*/
public class BoardPath {
public static long startTime;
public static long endTime;
public static void startAlgo() {
startTime = System.currentTimeMillis();
}
public static long endAlgo() {
endTime = System.currentTimeMillis();
return endTime - startTime;
}
public static int bpR(int start, int end) {
if (start == end) {
return 1;
} else if (start > end) {
return 0;
}
int count = 0;
for (int dice = 1; dice <= 6; dice++) {
count += bpR(start + dice, end);
}
return count;
}
public static int bpRS(int curr, int end, int strg[]) {
if (curr == end) {
return 1;
} else if (curr > end) {
return 0;
}
if (strg[curr] != 0) {
return strg[curr];
}
int count = 0;
for (int dice = 1; dice <= 6; dice++) {
count += bpRS(curr + dice, end, strg);
}
strg[curr] = count;
return count;
}
public static int bpIS(int curr, int end, int[] strg) {
strg[end] = 1;
for (int i = end - 1; i >= 0; i--) {
int count = 0;
for (int dice = 1; dice <= 6 && dice + i < strg.length; dice++) {
count += strg[i + dice];
}
strg[i] = count;
}
return strg[0];
}
}

View File

@ -0,0 +1,44 @@
package com.thealgorithms.dynamicprogramming;
/* A Naive recursive implementation
of 0-1 Knapsack problem */
public class BruteForceKnapsack {
// A utility function that returns
// maximum of two integers
static int max(int a, int b) {
return (a > b) ? a : b;
}
// Returns the maximum value that
// can be put in a knapsack of
// capacity W
static int knapSack(int W, int wt[], int val[], int n) {
// Base Case
if (n == 0 || W == 0) {
return 0;
}
// If weight of the nth item is
// more than Knapsack capacity W,
// then this item cannot be included
// in the optimal solution
if (wt[n - 1] > W) {
return knapSack(W, wt, val, n - 1);
} // Return the maximum of two cases:
// (1) nth item included
// (2) not included
else {
return max(val[n - 1] + knapSack(W - wt[n - 1], wt, val, n - 1), knapSack(W, wt, val, n - 1));
}
}
// Driver code
public static void main(String args[]) {
int val[] = new int[]{60, 100, 120};
int wt[] = new int[]{10, 20, 30};
int W = 50;
int n = val.length;
System.out.println(knapSack(W, wt, val, n));
}
}

View File

@ -0,0 +1,57 @@
package com.thealgorithms.dynamicprogramming;
/**
* This file contains an implementation of finding the nth CATALAN NUMBER using
* dynamic programming Wikipedia: https://en.wikipedia.org/wiki/Catalan_number
*
* Time Complexity: O(n^2) Space Complexity: O(n)
*
* @author AMRITESH ANAND (https://github.com/amritesh19)
*/
import java.util.Scanner;
public class CatalanNumber {
/**
* This method finds the nth Catalan number
*
* @param n input n which determines the nth Catalan number n should be less
* than equal to 50 as 50th Catalan number is 6,533,841,209,031,609,592 for
* n > 50, BigInteger class should be used instead long
*
* @return catalanArray[n] the nth Catalan number
*/
static long findNthCatalan(int n) {
// Array to store the results of subproblems i.e Catalan numbers from [1...n-1]
long catalanArray[] = new long[n + 1];
// Initialising C₀ = 1 and C₁ = 1
catalanArray[0] = 1;
catalanArray[1] = 1;
/**
* The Catalan numbers satisfy the recurrence relation C₀=1 and Cn = Σ
* (Ci * Cn-1-i), i = 0 to n-1 , n > 0
*/
for (int i = 2; i <= n; i++) {
catalanArray[i] = 0;
for (int j = 0; j < i; j++) {
catalanArray[i] += catalanArray[j] * catalanArray[i - j - 1];
}
}
return catalanArray[n];
}
// Main method
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number n to find nth Catalan number (n <= 50)");
int n = sc.nextInt();
System.out.println(n + "th Catalan number is " + findNthCatalan(n));
sc.close();
}
}

View File

@ -0,0 +1,85 @@
package com.thealgorithms.dynamicprogramming;
/**
* @author Varun Upadhyay (https://github.com/varunu28)
*/
public class CoinChange {
// Driver Program
public static void main(String[] args) {
int amount = 12;
int[] coins = {2, 4, 5};
System.out.println(
"Number of combinations of getting change for " + amount + " is: " + change(coins, amount));
System.out.println(
"Minimum number of coins required for amount :"
+ amount
+ " is: "
+ minimumCoins(coins, amount));
}
/**
* This method finds the number of combinations of getting change for a
* given amount and change coins
*
* @param coins The list of coins
* @param amount The amount for which we need to find the change Finds the
* number of combinations of change
*/
public static int change(int[] coins, int amount) {
int[] combinations = new int[amount + 1];
combinations[0] = 1;
for (int coin : coins) {
for (int i = coin; i < amount + 1; i++) {
combinations[i] += combinations[i - coin];
}
// Uncomment the below line to see the state of combinations for each coin
// printAmount(combinations);
}
return combinations[amount];
}
/**
* This method finds the minimum number of coins needed for a given amount.
*
* @param coins The list of coins
* @param amount The amount for which we need to find the minimum number of
* coins. Finds the the minimum number of coins that make a given value.
*/
public static int minimumCoins(int[] coins, int amount) {
// minimumCoins[i] will store the minimum coins needed for amount i
int[] minimumCoins = new int[amount + 1];
minimumCoins[0] = 0;
for (int i = 1; i <= amount; i++) {
minimumCoins[i] = Integer.MAX_VALUE;
}
for (int i = 1; i <= amount; i++) {
for (int coin : coins) {
if (coin <= i) {
int sub_res = minimumCoins[i - coin];
if (sub_res != Integer.MAX_VALUE && sub_res + 1 < minimumCoins[i]) {
minimumCoins[i] = sub_res + 1;
}
}
}
}
// Uncomment the below line to see the state of combinations for each coin
// printAmount(minimumCoins);
return minimumCoins[amount];
}
// A basic print method which prints all the contents of the array
public static void printAmount(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}

View File

@ -0,0 +1,63 @@
package com.thealgorithms.dynamicprogramming;
// Given N dice each with M faces, numbered from 1 to M, find the number of ways to get sum X.
// X is the summation of values on each face when all the dice are thrown.
/* The Naive approach is to find all the possible combinations of values from n dice and
keep on counting the results that sum to X. This can be done using recursion. */
// The above recursion solution exhibits overlapping subproblems.
/* Hence, storing the results of the solved sub-problems saves time.
And it can be done using Dynamic Programming(DP).
Following is implementation of Dynamic Programming approach. */
// Code ---->
// Java program to find number of ways to get sum 'x' with 'n'
// dice where every dice has 'm' faces
class DP {
/* The main function that returns the number of ways to get sum 'x' with 'n' dice and 'm' with m faces. */
public static long findWays(int m, int n, int x) {
/* Create a table to store the results of subproblems.
One extra row and column are used for simplicity
(Number of dice is directly used as row index and sum is directly used as column index).
The entries in 0th row and 0th column are never used. */
long[][] table = new long[n + 1][x + 1];
/* Table entries for only one dice */
for (int j = 1; j <= m && j <= x; j++) {
table[1][j] = 1;
}
/* Fill rest of the entries in table using recursive relation
i: number of dice, j: sum */
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= x; j++) {
for (int k = 1; k < j && k <= m; k++) {
table[i][j] += table[i - 1][j - k];
}
}
}
return table[n][x];
}
public static void main(String[] args) {
System.out.println(findWays(4, 2, 1));
System.out.println(findWays(2, 2, 3));
System.out.println(findWays(6, 3, 8));
System.out.println(findWays(4, 2, 5));
System.out.println(findWays(4, 3, 5));
}
}
/*
OUTPUT:
0
2
21
4
6
*/
// Time Complexity: O(m * n * x) where m is number of faces, n is number of dice and x is given sum.

View File

@ -0,0 +1,41 @@
package com.thealgorithms.dynamicprogramming;
// A Dynamic Programming based solution
// for 0-1 Knapsack problem
public class DyanamicProgrammingKnapsack {
static int max(int a, int b) {
return (a > b) ? a : b;
}
// Returns the maximum value that can
// be put in a knapsack of capacity W
static int knapSack(int W, int wt[], int val[], int n) {
int i, w;
int K[][] = new int[n + 1][W + 1];
// Build table K[][] in bottom up manner
for (i = 0; i <= n; i++) {
for (w = 0; w <= W; w++) {
if (i == 0 || w == 0) {
K[i][w] = 0;
} else if (wt[i - 1] <= w) {
K[i][w] = max(val[i - 1] + K[i - 1][w - wt[i - 1]], K[i - 1][w]);
} else {
K[i][w] = K[i - 1][w];
}
}
}
return K[n][W];
}
// Driver code
public static void main(String args[]) {
int val[] = new int[]{60, 100, 120};
int wt[] = new int[]{10, 20, 30};
int W = 50;
int n = val.length;
System.out.println(knapSack(W, wt, val, n));
}
}

View File

@ -0,0 +1,120 @@
package com.thealgorithms.dynamicprogramming;
/**
* A DynamicProgramming based solution for Edit Distance problem In Java
* Description of Edit Distance with an Example:
*
* <p>
* Edit distance is a way of quantifying how dissimilar two strings (e.g.,
* words) are to one another, by counting the minimum number of operations
* required to transform one string into the other. The distance operations are
* the removal, insertion, or substitution of a character in the string.
*
* <p>
*
* <p>
* The Distance between "kitten" and "sitting" is 3. A minimal edit script that
* transforms the former into the latter is:
*
* <p>
* kitten → sitten (substitution of "s" for "k") sitten → sittin (substitution
* of "i" for "e") sittin → sitting (insertion of "g" at the end).
*
* @author SUBHAM SANGHAI
*/
import java.util.Scanner;
public class EditDistance {
public static int minDistance(String word1, String word2) {
int len1 = word1.length();
int len2 = word2.length();
// len1+1, len2+1, because finally return dp[len1][len2]
int[][] dp = new int[len1 + 1][len2 + 1];
/* If second string is empty, the only option is to
insert all characters of first string into second*/
for (int i = 0; i <= len1; i++) {
dp[i][0] = i;
}
/* If first string is empty, the only option is to
insert all characters of second string into first*/
for (int j = 0; j <= len2; j++) {
dp[0][j] = j;
}
// iterate though, and check last char
for (int i = 0; i < len1; i++) {
char c1 = word1.charAt(i);
for (int j = 0; j < len2; j++) {
char c2 = word2.charAt(j);
// if last two chars equal
if (c1 == c2) {
// update dp value for +1 length
dp[i + 1][j + 1] = dp[i][j];
} else {
/* if two characters are different ,
then take the minimum of the various operations(i.e insertion,removal,substitution)*/
int replace = dp[i][j] + 1;
int insert = dp[i][j + 1] + 1;
int delete = dp[i + 1][j] + 1;
int min = replace > insert ? insert : replace;
min = delete > min ? min : delete;
dp[i + 1][j + 1] = min;
}
}
}
/* return the final answer , after traversing through both the strings*/
return dp[len1][len2];
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String s1, s2;
System.out.println("Enter the First String");
s1 = input.nextLine();
System.out.println("Enter the Second String");
s2 = input.nextLine();
// ans stores the final Edit Distance between the two strings
int ans = minDistance(s1, s2);
System.out.println(
"The minimum Edit Distance between \"" + s1 + "\" and \"" + s2 + "\" is " + ans);
input.close();
}
// edit distance problem
public static int editDistance(String s1, String s2) {
int[][] storage = new int[s1.length() + 1][s2.length() + 1];
return editDistance(s1, s2, storage);
}
public static int editDistance(String s1, String s2, int[][] storage) {
int m = s1.length();
int n = s2.length();
if (storage[m][n] > 0) {
return storage[m][n];
}
if (m == 0) {
storage[m][n] = n;
return storage[m][n];
}
if (n == 0) {
storage[m][n] = m;
return storage[m][n];
}
if (s1.charAt(0) == s2.charAt(0)) {
storage[m][n] = editDistance(s1.substring(1), s2.substring(1), storage);
return storage[m][n];
} else {
int op1 = editDistance(s1, s2.substring(1), storage);
int op2 = editDistance(s1.substring(1), s2, storage);
int op3 = editDistance(s1.substring(1), s2.substring(1), storage);
storage[m][n] = 1 + Math.min(op1, Math.min(op2, op3));
return storage[m][n];
}
}
}

View File

@ -0,0 +1,48 @@
package com.thealgorithms.dynamicprogramming;
/**
* DynamicProgramming solution for the Egg Dropping Puzzle
*/
public class EggDropping {
// min trials with n eggs and m floors
private static int minTrials(int n, int m) {
int[][] eggFloor = new int[n + 1][m + 1];
int result, x;
for (int i = 1; i <= n; i++) {
eggFloor[i][0] = 0; // Zero trial for zero floor.
eggFloor[i][1] = 1; // One trial for one floor
}
// j trials for only 1 egg
for (int j = 1; j <= m; j++) {
eggFloor[1][j] = j;
}
// Using bottom-up approach in DP
for (int i = 2; i <= n; i++) {
for (int j = 2; j <= m; j++) {
eggFloor[i][j] = Integer.MAX_VALUE;
for (x = 1; x <= j; x++) {
result = 1 + Math.max(eggFloor[i - 1][x - 1], eggFloor[i][j - x]);
// choose min of all values for particular x
if (result < eggFloor[i][j]) {
eggFloor[i][j] = result;
}
}
}
}
return eggFloor[n][m];
}
public static void main(String args[]) {
int n = 2, m = 4;
// result outputs min no. of trials in worst case for n eggs and m floors
int result = minTrials(n, m);
System.out.println(result);
}
}

View File

@ -0,0 +1,96 @@
package com.thealgorithms.dynamicprogramming;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
* @author Varun Upadhyay (https://github.com/varunu28)
*/
public class Fibonacci {
private static Map<Integer, Integer> map = new HashMap<>();
public static void main(String[] args) {
// Methods all returning [0, 1, 1, 2, 3, 5, ...] for n = [0, 1, 2, 3, 4, 5, ...]
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(fibMemo(n));
System.out.println(fibBotUp(n));
System.out.println(fibOptimized(n));
sc.close();
}
/**
* This method finds the nth fibonacci number using memoization technique
*
* @param n The input n for which we have to determine the fibonacci number
* Outputs the nth fibonacci number
*/
public static int fibMemo(int n) {
if (map.containsKey(n)) {
return map.get(n);
}
int f;
if (n <= 1) {
f = n;
} else {
f = fibMemo(n - 1) + fibMemo(n - 2);
map.put(n, f);
}
return f;
}
/**
* This method finds the nth fibonacci number using bottom up
*
* @param n The input n for which we have to determine the fibonacci number
* Outputs the nth fibonacci number
*/
public static int fibBotUp(int n) {
Map<Integer, Integer> fib = new HashMap<>();
for (int i = 0; i <= n; i++) {
int f;
if (i <= 1) {
f = i;
} else {
f = fib.get(i - 1) + fib.get(i - 2);
}
fib.put(i, f);
}
return fib.get(n);
}
/**
* This method finds the nth fibonacci number using bottom up
*
* @param n The input n for which we have to determine the fibonacci number
* Outputs the nth fibonacci number
* <p>
* This is optimized version of Fibonacci Program. Without using Hashmap and
* recursion. It saves both memory and time. Space Complexity will be O(1)
* Time Complexity will be O(n)
* <p>
* Whereas , the above functions will take O(n) Space.
* @author Shoaib Rayeen (https://github.com/shoaibrayeen)
*/
public static int fibOptimized(int n) {
if (n == 0) {
return 0;
}
int prev = 0, res = 1, next;
for (int i = 2; i <= n; i++) {
next = prev + res;
prev = res;
res = next;
}
return res;
}
}

View File

@ -0,0 +1,76 @@
package com.thealgorithms.dynamicprogramming;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Vector;
public class FordFulkerson {
static final int INF = 987654321;
// edges
static int V;
static int[][] capacity, flow;
public static void main(String[] args) {
System.out.println("V : 6");
V = 6;
capacity = new int[V][V];
capacity[0][1] = 12;
capacity[0][3] = 13;
capacity[1][2] = 10;
capacity[2][3] = 13;
capacity[2][4] = 3;
capacity[2][5] = 15;
capacity[3][2] = 7;
capacity[3][4] = 15;
capacity[4][5] = 17;
System.out.println("Max capacity in networkFlow : " + networkFlow(0, 5));
}
private static int networkFlow(int source, int sink) {
flow = new int[V][V];
int totalFlow = 0;
while (true) {
Vector<Integer> parent = new Vector<>(V);
for (int i = 0; i < V; i++) {
parent.add(-1);
}
Queue<Integer> q = new LinkedList<>();
parent.set(source, source);
q.add(source);
while (!q.isEmpty() && parent.get(sink) == -1) {
int here = q.peek();
q.poll();
for (int there = 0; there < V; ++there) {
if (capacity[here][there] - flow[here][there] > 0 && parent.get(there) == -1) {
q.add(there);
parent.set(there, here);
}
}
}
if (parent.get(sink) == -1) {
break;
}
int amount = INF;
String printer = "path : ";
StringBuilder sb = new StringBuilder();
for (int p = sink; p != source; p = parent.get(p)) {
amount = Math.min(capacity[parent.get(p)][p] - flow[parent.get(p)][p], amount);
sb.append(p + "-");
}
sb.append(source);
for (int p = sink; p != source; p = parent.get(p)) {
flow[parent.get(p)][p] += amount;
flow[p][parent.get(p)] -= amount;
}
totalFlow += amount;
printer += sb.reverse() + " / max flow : " + totalFlow;
System.out.println(printer);
}
return totalFlow;
}
}

View File

@ -0,0 +1,54 @@
package com.thealgorithms.dynamicprogramming;
import java.util.Scanner;
/**
* Program to implement Kadanes Algorithm to calculate maximum contiguous
* subarray sum of an array Time Complexity: O(n)
*
* @author Nishita Aggarwal
*/
public class KadaneAlgorithm {
/**
* This method implements Kadane's Algorithm
*
* @param arr The input array
* @return The maximum contiguous subarray sum of the array
*/
static int largestContiguousSum(int arr[]) {
int i, len = arr.length, cursum = 0, maxsum = Integer.MIN_VALUE;
if (len == 0) // empty array
{
return 0;
}
for (i = 0; i < len; i++) {
cursum += arr[i];
if (cursum > maxsum) {
maxsum = cursum;
}
if (cursum <= 0) {
cursum = 0;
}
}
return maxsum;
}
/**
* Main method
*
* @param args Command line arguments
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n, arr[], i;
n = sc.nextInt();
arr = new int[n];
for (i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
int maxContSum = largestContiguousSum(arr);
System.out.println(maxContSum);
sc.close();
}
}

View File

@ -0,0 +1,38 @@
package com.thealgorithms.dynamicprogramming;
/**
* A DynamicProgramming based solution for 0-1 Knapsack problem
*/
public class Knapsack {
private static int knapSack(int W, int wt[], int val[], int n) throws IllegalArgumentException {
if (wt == null || val == null) {
throw new IllegalArgumentException();
}
int i, w;
int rv[][] = new int[n + 1][W + 1]; // rv means return value
// Build table rv[][] in bottom up manner
for (i = 0; i <= n; i++) {
for (w = 0; w <= W; w++) {
if (i == 0 || w == 0) {
rv[i][w] = 0;
} else if (wt[i - 1] <= w) {
rv[i][w] = Math.max(val[i - 1] + rv[i - 1][w - wt[i - 1]], rv[i - 1][w]);
} else {
rv[i][w] = rv[i - 1][w];
}
}
}
return rv[n][W];
}
// Driver program to test above function
public static void main(String args[]) {
int val[] = new int[]{50, 100, 130};
int wt[] = new int[]{10, 20, 40};
int W = 50;
System.out.println(knapSack(W, wt, val, val.length));
}
}

View File

@ -0,0 +1,51 @@
package com.thealgorithms.dynamicprogramming;
import java.util.Arrays;
/**
* Recursive Solution for 0-1 knapsack with memoization
*/
public class KnapsackMemoization {
private static int[][] t;
// Returns the maximum value that can
// be put in a knapsack of capacity W
public static int knapsack(int[] wt, int[] value, int W, int n) {
if (t[n][W] != -1) {
return t[n][W];
}
if (n == 0 || W == 0) {
return 0;
}
if (wt[n - 1] <= W) {
t[n - 1][W - wt[n - 1]] = knapsack(wt, value, W - wt[n - 1], n - 1);
// Include item in the bag. In that case add the value of the item and call for the remaining items
int tmp1 = value[n - 1] + t[n - 1][W - wt[n - 1]];
// Don't include the nth item in the bag anl call for remaining item without reducing the weight
int tmp2 = knapsack(wt, value, W, n - 1);
t[n - 1][W] = tmp2;
// include the larger one
int tmp = tmp1 > tmp2 ? tmp1 : tmp2;
t[n][W] = tmp;
return tmp;
// If Weight for the item is more than the desired weight then don't include it
// Call for rest of the n-1 items
} else if (wt[n - 1] > W) {
t[n][W] = knapsack(wt, value, W, n - 1);
return t[n][W];
}
return -1;
}
// Driver code
public static void main(String args[]) {
int[] wt = {1, 3, 4, 5};
int[] value = {1, 4, 5, 7};
int W = 10;
t = new int[wt.length + 1][W + 1];
Arrays.stream(t).forEach(a -> Arrays.fill(a, -1));
int res = knapsack(wt, value, W, wt.length);
System.out.println("Maximum knapsack value " + res);
}
}

View File

@ -0,0 +1,53 @@
package com.thealgorithms.dynamicprogramming;
/**
* @author Kshitij VERMA (github.com/kv19971) LEVENSHTEIN DISTANCE dyamic
* programming implementation to show the difference between two strings
* (https://en.wikipedia.org/wiki/Levenshtein_distance)
*/
public class LevenshteinDistance {
private static int minimum(int a, int b, int c) {
if (a < b && a < c) {
return a;
} else if (b < a && b < c) {
return b;
} else {
return c;
}
}
private static int calculate_distance(String a, String b) {
int len_a = a.length() + 1;
int len_b = b.length() + 1;
int[][] distance_mat = new int[len_a][len_b];
for (int i = 0; i < len_a; i++) {
distance_mat[i][0] = i;
}
for (int j = 0; j < len_b; j++) {
distance_mat[0][j] = j;
}
for (int i = 0; i < len_a; i++) {
for (int j = 0; j < len_b; j++) {
int cost;
if (a.charAt(i) == b.charAt(j)) {
cost = 0;
} else {
cost = 1;
}
distance_mat[i][j]
= minimum(distance_mat[i - 1][j], distance_mat[i - 1][j - 1], distance_mat[i][j - 1])
+ cost;
}
}
return distance_mat[len_a - 1][len_b - 1];
}
public static void main(String[] args) {
String a = ""; // enter your string here
String b = ""; // enter your string here
System.out.print("Levenshtein distance between " + a + " and " + b + " is: ");
System.out.println(calculate_distance(a, b));
}
}

View File

@ -0,0 +1,70 @@
package com.thealgorithms.dynamicprogramming;
/*
* Problem Statement: -
* Find Longest Alternating Subsequence
* A sequence {x1, x2, .. xn} is alternating sequence if its elements satisfy one of the following relations :
x1 < x2 > x3 < x4 > x5 < …. xn or
x1 > x2 < x3 > x4 < x5 > …. xn
*/
public class LongestAlternatingSubsequence {
/* Function to return longest alternating subsequence length*/
static int AlternatingLength(int arr[], int n) {
/*
las[i][0] = Length of the longest
alternating subsequence ending at
index i and last element is
greater than its previous element
las[i][1] = Length of the longest
alternating subsequence ending at
index i and last element is
smaller than its previous
element
*/
int las[][] = new int[n][2]; // las = LongestAlternatingSubsequence
for (int i = 0; i < n; i++) {
las[i][0] = las[i][1] = 1;
}
int result = 1; // Initialize result
/* Compute values in bottom up manner */
for (int i = 1; i < n; i++) {
/* Consider all elements as previous of arr[i]*/
for (int j = 0; j < i; j++) {
/* If arr[i] is greater, then check with las[j][1] */
if (arr[j] < arr[i] && las[i][0] < las[j][1] + 1) {
las[i][0] = las[j][1] + 1;
}
/* If arr[i] is smaller, then check with las[j][0]*/
if (arr[j] > arr[i] && las[i][1] < las[j][0] + 1) {
las[i][1] = las[j][0] + 1;
}
}
/* Pick maximum of both values at index i */
if (result < Math.max(las[i][0], las[i][1])) {
result = Math.max(las[i][0], las[i][1]);
}
}
return result;
}
public static void main(String[] args) {
int arr[] = {10, 22, 9, 33, 49, 50, 31, 60};
int n = arr.length;
System.out.println("Length of Longest " + "alternating subsequence is " + AlternatingLength(arr, n));
}
}

View File

@ -0,0 +1,72 @@
package com.thealgorithms.dynamicprogramming;
class LongestCommonSubsequence {
public static String getLCS(String str1, String str2) {
// At least one string is null
if (str1 == null || str2 == null) {
return null;
}
// At least one string is empty
if (str1.length() == 0 || str2.length() == 0) {
return "";
}
String[] arr1 = str1.split("");
String[] arr2 = str2.split("");
// lcsMatrix[i][j] = LCS of first i elements of arr1 and first j characters of arr2
int[][] lcsMatrix = new int[arr1.length + 1][arr2.length + 1];
for (int i = 0; i < arr1.length + 1; i++) {
lcsMatrix[i][0] = 0;
}
for (int j = 1; j < arr2.length + 1; j++) {
lcsMatrix[0][j] = 0;
}
for (int i = 1; i < arr1.length + 1; i++) {
for (int j = 1; j < arr2.length + 1; j++) {
if (arr1[i - 1].equals(arr2[j - 1])) {
lcsMatrix[i][j] = lcsMatrix[i - 1][j - 1] + 1;
} else {
lcsMatrix[i][j]
= lcsMatrix[i - 1][j] > lcsMatrix[i][j - 1] ? lcsMatrix[i - 1][j] : lcsMatrix[i][j - 1];
}
}
}
return lcsString(str1, str2, lcsMatrix);
}
public static String lcsString(String str1, String str2, int[][] lcsMatrix) {
StringBuilder lcs = new StringBuilder();
int i = str1.length(), j = str2.length();
while (i > 0 && j > 0) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
lcs.append(str1.charAt(i - 1));
i--;
j--;
} else if (lcsMatrix[i - 1][j] > lcsMatrix[i][j - 1]) {
i--;
} else {
j--;
}
}
return lcs.reverse().toString();
}
public static void main(String[] args) {
String str1 = "DSGSHSRGSRHTRD";
String str2 = "DATRGAGTSHS";
String lcs = getLCS(str1, str2);
// Print LCS
if (lcs != null) {
System.out.println("String 1: " + str1);
System.out.println("String 2: " + str2);
System.out.println("LCS: " + lcs);
System.out.println("LCS length: " + lcs.length());
}
}
}

View File

@ -0,0 +1,110 @@
package com.thealgorithms.dynamicprogramming;
import java.util.Scanner;
/**
* @author Afrizal Fikri (https://github.com/icalF)
*/
public class LongestIncreasingSubsequence {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
System.out.println(LIS(arr));
System.out.println(findLISLen(arr));
sc.close();
}
private static int upperBound(int[] ar, int l, int r, int key) {
while (l < r - 1) {
int m = (l + r) >>> 1;
if (ar[m] >= key) {
r = m;
} else {
l = m;
}
}
return r;
}
private static int LIS(int[] array) {
int N = array.length;
if (N == 0) {
return 0;
}
int[] tail = new int[N];
// always points empty slot in tail
int length = 1;
tail[0] = array[0];
for (int i = 1; i < N; i++) {
// new smallest value
if (array[i] < tail[0]) {
tail[0] = array[i];
} // array[i] extends largest subsequence
else if (array[i] > tail[length - 1]) {
tail[length++] = array[i];
} // array[i] will become end candidate of an existing subsequence or
// Throw away larger elements in all LIS, to make room for upcoming grater elements than
// array[i]
// (and also, array[i] would have already appeared in one of LIS, identify the location and
// replace it)
else {
tail[upperBound(tail, -1, length - 1, array[i])] = array[i];
}
}
return length;
}
/**
* @author Alon Firestein (https://github.com/alonfirestein)
*/
// A function for finding the length of the LIS algorithm in O(nlogn) complexity.
public static int findLISLen(int a[]) {
int size = a.length;
int arr[] = new int[size];
arr[0] = a[0];
int lis = 1;
for (int i = 1; i < size; i++) {
int index = binarySearchBetween(arr, lis, a[i]);
arr[index] = a[i];
if (index > lis) {
lis++;
}
}
return lis;
}
// O(logn)
private static int binarySearchBetween(int[] t, int end, int key) {
int left = 0;
int right = end;
if (key < t[0]) {
return 0;
}
if (key > t[end]) {
return end + 1;
}
while (left < right - 1) {
int middle = (left + right) / 2;
if (t[middle] < key) {
left = middle;
} else {
right = middle;
}
}
return right;
}
}

View File

@ -0,0 +1,61 @@
package com.thealgorithms.dynamicprogramming;
/**
* Algorithm explanation
* https://www.educative.io/edpresso/longest-palindromic-subsequence-algorithm
*/
public class LongestPalindromicSubsequence {
public static void main(String[] args) {
String a = "BBABCBCAB";
String b = "BABCBAB";
String aLPS = LPS(a);
String bLPS = LPS(b);
System.out.println(a + " => " + aLPS);
System.out.println(b + " => " + bLPS);
}
public static String LPS(String original) throws IllegalArgumentException {
StringBuilder reverse = new StringBuilder(original);
reverse = reverse.reverse();
return recursiveLPS(original, reverse.toString());
}
private static String recursiveLPS(String original, String reverse) {
String bestResult = "";
// no more chars, then return empty
if (original.length() == 0 || reverse.length() == 0) {
bestResult = "";
} else {
// if the last chars match, then remove it from both strings and recur
if (original.charAt(original.length() - 1) == reverse.charAt(reverse.length() - 1)) {
String bestSubResult
= recursiveLPS(
original.substring(0, original.length() - 1),
reverse.substring(0, reverse.length() - 1));
bestResult = reverse.charAt(reverse.length() - 1) + bestSubResult;
} else {
// otherwise (1) ignore the last character of reverse, and recur on original and updated
// reverse again
// (2) ignore the last character of original and recur on the updated original and reverse
// again
// then select the best result from these two subproblems.
String bestSubResult1 = recursiveLPS(original, reverse.substring(0, reverse.length() - 1));
String bestSubResult2 = recursiveLPS(original.substring(0, original.length() - 1), reverse);
if (bestSubResult1.length() > bestSubResult2.length()) {
bestResult = bestSubResult1;
} else {
bestResult = bestSubResult2;
}
}
}
return bestResult;
}
}

View File

@ -0,0 +1,54 @@
package com.thealgorithms.dynamicprogramming;
/*
* Algorithm explanation https://leetcode.com/problems/longest-palindromic-substring/
*/
public class LongestPalindromicSubstring {
public static void main(String[] args) {
String a = "babad";
String b = "cbbd";
String aLPS = LPS(a);
String bLPS = LPS(b);
System.out.println(a + " => " + aLPS);
System.out.println(b + " => " + bLPS);
}
private static String LPS(String input) {
if (input == null || input.length() == 0) {
return input;
}
boolean arr[][] = new boolean[input.length()][input.length()];
int start = 0, end = 0;
for (int g = 0; g < input.length(); g++) {
for (int i = 0, j = g; j < input.length(); i++, j++) {
if (g == 0) {
arr[i][j] = true;
} else if (g == 1) {
if (input.charAt(i) == input.charAt(j)) {
arr[i][j] = true;
} else {
arr[i][j] = false;
}
} else {
if (input.charAt(i) == input.charAt(j) && arr[i + 1][j - 1]) {
arr[i][j] = true;
} else {
arr[i][j] = false;
}
}
if (arr[i][j]) {
start = i;
end = j;
}
}
}
return input.substring(start, end + 1);
}
}

View File

@ -0,0 +1,58 @@
package com.thealgorithms.dynamicprogramming;
import java.util.Scanner;
/**
* Given a string containing just the characters '(' and ')', find the length of
* the longest valid (well-formed) parentheses substring.
*
* @author Libin Yang (https://github.com/yanglbme)
* @since 2018/10/5
*/
public class LongestValidParentheses {
public static int getLongestValidParentheses(String s) {
if (s == null || s.length() < 2) {
return 0;
}
char[] chars = s.toCharArray();
int n = chars.length;
int[] res = new int[n];
res[0] = 0;
res[1] = chars[1] == ')' && chars[0] == '(' ? 2 : 0;
int max = res[1];
for (int i = 2; i < n; ++i) {
if (chars[i] == ')') {
if (chars[i - 1] == '(') {
res[i] = res[i - 2] + 2;
} else {
int index = i - res[i - 1] - 1;
if (index >= 0 && chars[index] == '(') {
// ()(())
res[i] = res[i - 1] + 2 + (index - 1 >= 0 ? res[index - 1] : 0);
}
}
}
max = Math.max(max, res[i]);
}
return max;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true) {
String str = sc.nextLine();
if ("quit".equals(str)) {
break;
}
System.out.println("Len is: " + getLongestValidParentheses(str));
}
sc.close();
}
}

View File

@ -0,0 +1,139 @@
package com.thealgorithms.dynamicprogramming;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class MatrixChainMultiplication {
private static Scanner scan = new Scanner(System.in);
private static ArrayList<Matrix> mArray = new ArrayList<>();
private static int size;
private static int[][] m;
private static int[][] s;
private static int[] p;
public static void main(String[] args) {
int count = 1;
while (true) {
String[] mSize = input("input size of matrix A(" + count + ") ( ex. 10 20 ) : ");
int col = Integer.parseInt(mSize[0]);
if (col == 0) {
break;
}
int row = Integer.parseInt(mSize[1]);
Matrix matrix = new Matrix(count, col, row);
mArray.add(matrix);
count++;
}
for (Matrix m : mArray) {
System.out.format("A(%d) = %2d x %2d%n", m.count(), m.col(), m.row());
}
size = mArray.size();
m = new int[size + 1][size + 1];
s = new int[size + 1][size + 1];
p = new int[size + 1];
for (int i = 0; i < size + 1; i++) {
Arrays.fill(m[i], -1);
Arrays.fill(s[i], -1);
}
for (int i = 0; i < p.length; i++) {
p[i] = i == 0 ? mArray.get(i).col() : mArray.get(i - 1).row();
}
matrixChainOrder();
for (int i = 0; i < size; i++) {
System.out.print("-------");
}
System.out.println();
printArray(m);
for (int i = 0; i < size; i++) {
System.out.print("-------");
}
System.out.println();
printArray(s);
for (int i = 0; i < size; i++) {
System.out.print("-------");
}
System.out.println();
System.out.println("Optimal solution : " + m[1][size]);
System.out.print("Optimal parens : ");
printOptimalParens(1, size);
}
private static void printOptimalParens(int i, int j) {
if (i == j) {
System.out.print("A" + i);
} else {
System.out.print("(");
printOptimalParens(i, s[i][j]);
printOptimalParens(s[i][j] + 1, j);
System.out.print(")");
}
}
private static void printArray(int[][] array) {
for (int i = 1; i < size + 1; i++) {
for (int j = 1; j < size + 1; j++) {
System.out.print(String.format("%7d", array[i][j]));
}
System.out.println();
}
}
private static void matrixChainOrder() {
for (int i = 1; i < size + 1; i++) {
m[i][i] = 0;
}
for (int l = 2; l < size + 1; l++) {
for (int i = 1; i < size - l + 2; i++) {
int j = i + l - 1;
m[i][j] = Integer.MAX_VALUE;
for (int k = i; k < j; k++) {
int q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if (q < m[i][j]) {
m[i][j] = q;
s[i][j] = k;
}
}
}
}
}
private static String[] input(String string) {
System.out.print(string);
return (scan.nextLine().split(" "));
}
}
class Matrix {
private int count;
private int col;
private int row;
Matrix(int count, int col, int row) {
this.count = count;
this.col = col;
this.row = row;
}
int count() {
return count;
}
int col() {
return col;
}
int row() {
return row;
}
}

View File

@ -0,0 +1,47 @@
package com.thealgorithms.dynamicprogramming;
// Matrix-chain Multiplication
// Problem Statement
// we have given a chain A1,A2,...,Ani of n matrices, where for i = 1,2,...,n,
// matrix Ai has dimension pi1 ×pi
// , fully parenthesize the product A1A2 ···An in a way that
// minimizes the number of scalar multiplications.
public class MatrixChainRecursiveTopDownMemoisation {
static int Memoized_Matrix_Chain(int p[]) {
int n = p.length;
int m[][] = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
m[i][j] = Integer.MAX_VALUE;
}
}
return Lookup_Chain(m, p, 1, n - 1);
}
static int Lookup_Chain(int m[][], int p[], int i, int j) {
if (i == j) {
m[i][j] = 0;
return m[i][j];
}
if (m[i][j] < Integer.MAX_VALUE) {
return m[i][j];
} else {
for (int k = i; k < j; k++) {
int q = Lookup_Chain(m, p, i, k) + Lookup_Chain(m, p, k + 1, j) + (p[i - 1] * p[k] * p[j]);
if (q < m[i][j]) {
m[i][j] = q;
}
}
}
return m[i][j];
}
// in this code we are taking the example of 4 matrixes whose orders are 1x2,2x3,3x4,4x5 respectively
// output should be Minimum number of multiplications is 38
public static void main(String[] args) {
int arr[] = {1, 2, 3, 4, 5};
System.out.println("Minimum number of multiplications is " + Memoized_Matrix_Chain(arr));
}
}

View File

@ -0,0 +1,64 @@
package com.thealgorithms.dynamicprogramming;
// Here is the top-down approach of
// dynamic programming
public class MemoizationTechniqueKnapsack {
// A utility function that returns
// maximum of two integers
static int max(int a, int b) {
return (a > b) ? a : b;
}
// Returns the value of maximum profit
static int knapSackRec(int W, int wt[], int val[], int n, int[][] dp) {
// Base condition
if (n == 0 || W == 0) {
return 0;
}
if (dp[n][W] != -1) {
return dp[n][W];
}
if (wt[n - 1] > W) // Store the value of function call
// stack in table before return
{
return dp[n][W] = knapSackRec(W, wt, val, n - 1, dp);
} else // Return value of table after storing
{
return dp[n][W]
= max(
(val[n - 1] + knapSackRec(W - wt[n - 1], wt, val, n - 1, dp)),
knapSackRec(W, wt, val, n - 1, dp));
}
}
static int knapSack(int W, int wt[], int val[], int N) {
// Declare the table dynamically
int dp[][] = new int[N + 1][W + 1];
// Loop to initially filled the
// table with -1
for (int i = 0; i < N + 1; i++) {
for (int j = 0; j < W + 1; j++) {
dp[i][j] = -1;
}
}
return knapSackRec(W, wt, val, N, dp);
}
// Driver Code
public static void main(String[] args) {
int val[] = {60, 100, 120};
int wt[] = {10, 20, 30};
int W = 50;
int N = val.length;
System.out.println(knapSack(W, wt, val, N));
}
}

View File

@ -0,0 +1,81 @@
package com.thealgorithms.dynamicprogramming;
/*
Given the following grid with length m and width n:
\---\---\---\ (n)
\ 1 \ 3 \ 1 \
\---\---\---\
\ 1 \ 5 \ 1 \
\---\---\---\
\ 4 \ 2 \ 1 \
\---\---\---\
(m)
Find the path where its sum is the smallest.
All numbers given are positive.
The Time Complexity of your algorithm should be smaller than or equal to O(mn).
The Space Complexity of your algorithm should be smaller than or equal to O(mn).
You can only move from the top left corner to the down right corner.
You can only move one step down or right.
EXAMPLE:
INPUT: grid = [[1,3,1],[1,5,1],[4,2,1]]
OUTPUT: 7
EXPLANATIONS: 1 + 3 + 1 + 1 + 1 = 7
For more information see https://www.geeksforgeeks.org/maximum-path-sum-matrix/
*/
public class MinimumPathSum {
public void testRegular() {
int[][] grid = {
{1, 3, 1},
{1, 5, 1},
{4, 2, 1}
};
System.out.println(minimumPathSum(grid));
}
public void testLessColumns() {
int[][] grid = {
{1, 2},
{5, 6},
{1, 1}
};
System.out.println(minimumPathSum(grid));
}
public void testLessRows() {
int[][] grid = {
{2, 3, 3},
{7, 2, 1}
};
System.out.println(minimumPathSum(grid));
}
public void testOneRowOneColumn() {
int[][] grid = {{2}};
System.out.println(minimumPathSum(grid));
}
public static int minimumPathSum(int[][] grid) {
int m = grid.length, n = grid[0].length;
if (n == 0) {
return 0;
}
int[][] dp = new int[m][n];
dp[0][0] = grid[0][0];
for (int i = 0; i < n - 1; i++) {
dp[0][i + 1] = dp[0][i] + grid[0][i + 1];
}
for (int i = 0; i < m - 1; i++) {
dp[i + 1][0] = dp[i][0] + grid[i + 1][0];
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[m - 1][n - 1];
}
}

View File

@ -0,0 +1,88 @@
package com.thealgorithms.dynamicprogramming;
// Partition a set into two subsets such that the difference of subset sums is minimum
/*
Input: arr[] = {1, 6, 11, 5}
Output: 1
Explanation:
Subset1 = {1, 5, 6}, sum of Subset1 = 12
Subset2 = {11}, sum of Subset2 = 11
Input: arr[] = {36, 7, 46, 40}
Output: 23
Explanation:
Subset1 = {7, 46} ; sum of Subset1 = 53
Subset2 = {36, 40} ; sum of Subset2 = 76
*/
public class MinimumSumPartition {
public static int subSet(int[] arr) {
int n = arr.length;
int sum = getSum(arr);
boolean[][] dp = new boolean[n + 1][sum + 1];
for (int i = 0; i <= n; i++) {
dp[i][0] = true;
}
for (int j = 0; j <= sum; j++) {
dp[0][j] = false;
}
// fill dp array
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= sum; j++) {
if (arr[i - 1] < j) {
dp[i][j] = dp[i - 1][j - arr[i - 1]] || dp[i - 1][j];
} else if (arr[i - 1] == j) {
dp[i][j] = true;
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
// fill the index array
int[] index = new int[sum];
int p = 0;
for (int i = 0; i <= sum / 2; i++) {
if (dp[n][i]) {
index[p++] = i;
}
}
return getMin(index, sum);
}
/**
* Calculate sum of array elements
*
* @param arr the array
* @return sum of given array
*/
public static int getSum(int[] arr) {
int sum = 0;
for (int temp : arr) {
sum += temp;
}
return sum;
}
public static int getMin(int[] arr, int sum) {
if (arr.length == 0) {
return 0;
}
int min = Integer.MAX_VALUE;
for (int temp : arr) {
min = Math.min(min, sum - 2 * temp);
}
return min;
}
/**
* Driver Code
*/
public static void main(String[] args) {
assert subSet(new int[]{1, 6, 11, 5}) == 1;
assert subSet(new int[]{36, 7, 46, 40}) == 23;
assert subSet(new int[]{1, 2, 3, 9}) == 3;
}
}

View File

@ -0,0 +1,91 @@
package com.thealgorithms.dynamicprogramming;
import java.util.Scanner;
/**
* @file @brief Implements [Palindrome
* Partitioning](https://leetcode.com/problems/palindrome-partitioning-ii/)
* algorithm, giving you the minimum number of partitions you need to make
*
* @details palindrome partitioning uses dynamic programming and goes to all the
* possible partitions to find the minimum you are given a string and you need
* to give minimum number of partitions needed to divide it into a number of
* palindromes [Palindrome Partitioning]
* (https://www.geeksforgeeks.org/palindrome-partitioning-dp-17/) overall time
* complexity O(n^2) For example: example 1:- String : "nitik" Output : 2 => "n
* | iti | k" For example: example 2:- String : "ababbbabbababa" Output : 3 =>
* "aba | b | bbabb | ababa"
* @author [Syed] (https://github.com/roeticvampire)
*/
public class PalindromicPartitioning {
public static int minimalpartitions(String word) {
int len = word.length();
/* We Make two arrays to create a bottom-up solution.
minCuts[i] = Minimum number of cuts needed for palindrome partitioning of substring word[0..i]
isPalindrome[i][j] = true if substring str[i..j] is palindrome
Base Condition: C[i] is 0 if P[0][i]= true
*/
int[] minCuts = new int[len];
boolean[][] isPalindrome = new boolean[len][len];
int i, j, L; // different looping variables
// Every substring of length 1 is a palindrome
for (i = 0; i < len; i++) {
isPalindrome[i][i] = true;
}
/* L is substring length. Build the solution in bottom up manner by considering all substrings of length starting from 2 to n. */
for (L = 2; L <= len; L++) {
// For substring of length L, set different possible starting indexes
for (i = 0; i < len - L + 1; i++) {
j = i + L - 1; // Ending index
// If L is 2, then we just need to
// compare two characters. Else need to
// check two corner characters and value
// of P[i+1][j-1]
if (L == 2) {
isPalindrome[i][j] = (word.charAt(i) == word.charAt(j));
} else {
if ((word.charAt(i) == word.charAt(j)) && isPalindrome[i + 1][j - 1]) {
isPalindrome[i][j] = true;
} else {
isPalindrome[i][j] = false;
}
}
}
}
//We find the minimum for each index
for (i = 0; i < len; i++) {
if (isPalindrome[0][i] == true) {
minCuts[i] = 0;
} else {
minCuts[i] = Integer.MAX_VALUE;
for (j = 0; j < i; j++) {
if (isPalindrome[j + 1][i] == true && 1 + minCuts[j] < minCuts[i]) {
minCuts[i] = 1 + minCuts[j];
}
}
}
}
// Return the min cut value for complete
// string. i.e., str[0..n-1]
return minCuts[len - 1];
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String word;
System.out.println("Enter the First String");
word = input.nextLine();
// ans stores the final minimal cut count needed for partitioning
int ans = minimalpartitions(word);
System.out.println(
"The minimum cuts needed to partition \"" + word + "\" into palindromes is " + ans);
input.close();
}
}

View File

@ -0,0 +1,171 @@
package com.thealgorithms.dynamicprogramming;
/**
* Given a text and wildcard pattern implement a wildcard pattern matching
* algorithm that finds if wildcard is matched with text. The matching should
* cover the entire text ?-> matches single characters *-> match the sequence of
* characters
*
*/
/**
* For calculation of Time and Space Complexity. Let N be length of src and M be
* length of pat
*
*/
public class RegexMatching {
// Method 1: Using Recursion
// Time Complexity=0(2^(N+M)) Space Complexity=Recursion Extra Space
static boolean regexRecursion(String src, String pat) {
if (src.length() == 0 && pat.length() == 0) {
return true;
}
if (src.length() != 0 && pat.length() == 0) {
return false;
}
if (src.length() == 0 && pat.length() != 0) {
for (int i = 0; i < pat.length(); i++) {
if (pat.charAt(i) != '*') {
return false;
}
}
return true;
}
char chs = src.charAt(0);
char chp = pat.charAt(0);
String ros = src.substring(1);
String rop = pat.substring(1);
boolean ans;
if (chs == chp || chp == '?') {
ans = regexRecursion(ros, rop);
} else if (chp == '*') {
boolean blank = regexRecursion(src, rop);
boolean multiple = regexRecursion(ros, pat);
ans = blank || multiple;
} else {
ans = false;
}
return ans;
}
// Method 2: Using Recursion and breaking string using virtual index
// Time Complexity=0(2^(N+M)) Space Complexity=Recursion Extra Space
static boolean regexRecursion(String src, String pat, int svidx, int pvidx) {
if (src.length() == svidx && pat.length() == pvidx) {
return true;
}
if (src.length() != svidx && pat.length() == pvidx) {
return false;
}
if (src.length() == svidx && pat.length() != pvidx) {
for (int i = pvidx; i < pat.length(); i++) {
if (pat.charAt(i) != '*') {
return false;
}
}
return true;
}
char chs = src.charAt(svidx);
char chp = pat.charAt(pvidx);
boolean ans;
if (chs == chp || chp == '?') {
ans = regexRecursion(src, pat, svidx + 1, pvidx + 1);
} else if (chp == '*') {
boolean blank = regexRecursion(src, pat, svidx, pvidx + 1);
boolean multiple = regexRecursion(src, pat, svidx + 1, pvidx);
ans = blank || multiple;
} else {
ans = false;
}
return ans;
}
// Method 3: Top-Down DP(Memoization)
// Time Complexity=0(N*M) Space Complexity=0(N*M)+Recursion Extra Space
static boolean regexRecursion(String src, String pat, int svidx, int pvidx, int[][] strg) {
if (src.length() == svidx && pat.length() == pvidx) {
return true;
}
if (src.length() != svidx && pat.length() == pvidx) {
return false;
}
if (src.length() == svidx && pat.length() != pvidx) {
for (int i = pvidx; i < pat.length(); i++) {
if (pat.charAt(i) != '*') {
return false;
}
}
return true;
}
if (strg[svidx][pvidx] != 0) {
return strg[svidx][pvidx] == 1 ? false : true;
}
char chs = src.charAt(svidx);
char chp = pat.charAt(pvidx);
boolean ans;
if (chs == chp || chp == '?') {
ans = regexRecursion(src, pat, svidx + 1, pvidx + 1, strg);
} else if (chp == '*') {
boolean blank = regexRecursion(src, pat, svidx, pvidx + 1, strg);
boolean multiple = regexRecursion(src, pat, svidx + 1, pvidx, strg);
ans = blank || multiple;
} else {
ans = false;
}
strg[svidx][pvidx] = ans == false ? 1 : 2;
return ans;
}
// Method 4: Bottom-Up DP(Tabulation)
// Time Complexity=0(N*M) Space Complexity=0(N*M)
static boolean regexBU(String src, String pat) {
boolean strg[][] = new boolean[src.length() + 1][pat.length() + 1];
strg[src.length()][pat.length()] = true;
for (int row = src.length(); row >= 0; row--) {
for (int col = pat.length() - 1; col >= 0; col--) {
if (row == src.length()) {
if (pat.charAt(col) == '*') {
strg[row][col] = strg[row][col + 1];
} else {
strg[row][col] = false;
}
} else {
char chs = src.charAt(row);
char chp = pat.charAt(col);
boolean ans;
if (chs == chp || chp == '?') {
ans = strg[row + 1][col + 1];
} else if (chp == '*') {
boolean blank = strg[row][col + 1];
boolean multiple = strg[row + 1][col];
ans = blank || multiple;
} else {
ans = false;
}
strg[row][col] = ans;
}
}
}
return strg[0][0];
}
public static void main(String[] args) {
String src = "aa";
String pat = "*";
System.out.println("Method 1: " + regexRecursion(src, pat));
System.out.println("Method 2: " + regexRecursion(src, pat, 0, 0));
System.out.println("Method 3: " + regexRecursion(src, pat, 0, 0, new int[src.length()][pat.length()]));
System.out.println("Method 4: " + regexBU(src, pat));
}
}
// Memoization vs Tabulation : https://www.geeksforgeeks.org/tabulation-vs-memoization/
// Question Link : https://practice.geeksforgeeks.org/problems/wildcard-pattern-matching/1

View File

@ -0,0 +1,32 @@
package com.thealgorithms.dynamicprogramming;
/**
* A DynamicProgramming solution for Rod cutting problem Returns the best
* obtainable price for a rod of length n and price[] as prices of different
* pieces
*/
public class RodCutting {
private static int cutRod(int[] price, int n) {
int val[] = new int[n + 1];
val[0] = 0;
for (int i = 1; i <= n; i++) {
int max_val = Integer.MIN_VALUE;
for (int j = 0; j < i; j++) {
max_val = Math.max(max_val, price[j] + val[i - j - 1]);
}
val[i] = max_val;
}
return val[n];
}
// main function to test
public static void main(String args[]) {
int[] arr = new int[]{2, 5, 13, 19, 20};
int result = cutRod(arr, arr.length);
System.out.println("Maximum Obtainable Value is " + result);
}
}

View File

@ -0,0 +1,57 @@
package com.thealgorithms.dynamicprogramming;
// Java program to find length of the shortest supersequence
class ShortestSuperSequence {
// Function to find length of the
// shortest supersequence of X and Y.
static int shortestSuperSequence(String X, String Y) {
int m = X.length();
int n = Y.length();
// find lcs
int l = lcs(X, Y, m, n);
// Result is sum of input string
// lengths - length of lcs
return (m + n - l);
}
// Returns length of LCS
// for X[0..m - 1], Y[0..n - 1]
static int lcs(String X, String Y, int m, int n) {
int[][] L = new int[m + 1][n + 1];
int i, j;
// Following steps build L[m + 1][n + 1]
// in bottom up fashion. Note that
// L[i][j] contains length of LCS
// of X[0..i - 1]and Y[0..j - 1]
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0) {
L[i][j] = 0;
} else if (X.charAt(i - 1) == Y.charAt(j - 1)) {
L[i][j] = L[i - 1][j - 1] + 1;
} else {
L[i][j] = Math.max(L[i - 1][j],
L[i][j - 1]);
}
}
}
// L[m][n] contains length of LCS
// for X[0..n - 1] and Y[0..m - 1]
return L[m][n];
}
// Driver code
public static void main(String args[]) {
String X = "AGGTAB";
String Y = "GXTXAYB";
System.out.println("Length of the shortest "
+ "supersequence is "
+ shortestSuperSequence(X, Y));
}
}

View File

@ -0,0 +1,48 @@
package com.thealgorithms.dynamicprogramming;
public class SubsetSum {
/**
* Driver Code
*/
public static void main(String[] args) {
int[] arr = new int[]{50, 4, 10, 15, 34};
assert subsetSum(arr, 64);
/* 4 + 10 + 15 + 34 = 64 */
assert subsetSum(arr, 99);
/* 50 + 15 + 34 = 99 */
assert !subsetSum(arr, 5);
assert !subsetSum(arr, 66);
}
/**
* Test if a set of integers contains a subset that sum to a given integer.
*
* @param arr the array contains integers.
* @param sum target sum of subset.
* @return {@code true} if subset exists, otherwise {@code false}.
*/
private static boolean subsetSum(int[] arr, int sum) {
int n = arr.length;
boolean[][] isSum = new boolean[n + 2][sum + 1];
isSum[n + 1][0] = true;
for (int i = 1; i <= sum; i++) {
isSum[n + 1][i] = false;
}
for (int i = n; i > 0; i--) {
isSum[i][0] = true;
for (int j = 1; j <= arr[i - 1] - 1; j++) {
if (j <= sum) {
isSum[i][j] = isSum[i + 1][j];
}
}
for (int j = arr[i - 1]; j <= sum; j++) {
isSum[i][j] = (isSum[i + 1][j] || isSum[i + 1][j - arr[i - 1]]);
}
}
return isSum[1][sum];
}
}

View File

@ -0,0 +1,30 @@
package com.thealgorithms.dynamicprogramming;
public class Sum_Of_Subset {
public static void main(String[] args) {
int[] arr = {7, 3, 2, 5, 8};
int Key = 14;
if (subsetSum(arr, arr.length - 1, Key)) {
System.out.print("Yes, that sum exists");
} else {
System.out.print("Nope, that number does not exist");
}
}
public static boolean subsetSum(int[] arr, int num, int Key) {
if (Key == 0) {
return true;
}
if (num < 0 || Key < 0) {
return false;
}
boolean include = subsetSum(arr, num - 1, Key - arr[num]);
boolean exclude = subsetSum(arr, num - 1, Key);
return include || exclude;
}
}

View File

@ -0,0 +1,88 @@
package com.thealgorithms.dynamicprogramming;
/**
* Imagine you have a collection of N wines placed next to each other on the
* shelf. The price of ith wine is pi(Prices of different wines are different).
* Because wine gets better every year supposing today is year 1, on year y the
* price would be y*pi i.e y times the value of the initial year. You want to
* sell all wines but you have to sell one wine per year. One more constraint on
* each year you are allowed to sell either leftmost or rightmost wine on the
* shelf. You are not allowed to reorder. You have to find the maximum profit
*
*/
public class WineProblem {
// Method 1: Using Recursion
// Time Complexity=0(2^N) Space Complexity=Recursion extra space
public static int WPRecursion(int[] arr, int si, int ei) {
int n = arr.length;
int year = (n - (ei - si + 1)) + 1;
if (si == ei) {
return arr[si] * year;
}
int start = WPRecursion(arr, si + 1, ei) + arr[si] * year;
int end = WPRecursion(arr, si, ei - 1) + arr[ei] * year;
int ans = Math.max(start, end);
return ans;
}
// Method 2: Top-Down DP(Memoization)
// Time Complexity=0(N*N) Space Complexity=0(N*N)+Recursion extra space
public static int WPTD(int[] arr, int si, int ei, int[][] strg) {
int n = arr.length;
int year = (n - (ei - si + 1)) + 1;
if (si == ei) {
return arr[si] * year;
}
if (strg[si][ei] != 0) {
return strg[si][ei];
}
int start = WPTD(arr, si + 1, ei, strg) + arr[si] * year;
int end = WPTD(arr, si, ei - 1, strg) + arr[ei] * year;
int ans = Math.max(start, end);
strg[si][ei] = ans;
return ans;
}
// Method 3: Bottom-Up DP(Tabulation)
// Time Complexity=0(N*N/2)->0(N*N) Space Complexity=0(N*N)
public static int WPBU(int[] arr) {
int n = arr.length;
int[][] strg = new int[n][n];
for (int slide = 0; slide <= n - 1; slide++) {
for (int si = 0; si <= n - slide - 1; si++) {
int ei = si + slide;
int year = (n - (ei - si + 1)) + 1;
if (si == ei) {
strg[si][ei] = arr[si] * year;
} else {
int start = strg[si + 1][ei] + arr[si] * year;
int end = strg[si][ei - 1] + arr[ei] * year;
strg[si][ei] = Math.max(start, end);
}
}
}
return strg[0][n - 1];
}
public static void main(String[] args) {
int[] arr = {2, 3, 5, 1, 4};
System.out.println("Method 1: " + WPRecursion(arr, 0, arr.length - 1));
System.out.println("Method 2: " + WPTD(arr, 0, arr.length - 1, new int[arr.length][arr.length]));
System.out.println("Method 3: " + WPBU(arr));
}
}
// Memoization vs Tabulation : https://www.geeksforgeeks.org/tabulation-vs-memoization/
// Question Link : https://www.geeksforgeeks.org/maximum-profit-sale-wines/