Skip to content

Commit

Permalink
Enhancements in DP approach
Browse files Browse the repository at this point in the history
  • Loading branch information
rusty-sj committed Aug 29, 2020
1 parent 96484b6 commit cae8560
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 20 deletions.
45 changes: 35 additions & 10 deletions CoinChange_LC322.java
@@ -1,29 +1,54 @@
/**
* Use Dynamic Programming bottom up approach
* Dynamic programming top down approach
*/

// Time Complexity: O (N*K) N=coins, K=amount
// Space Complexity: O (K) due to memoization
// Did this code successfully run on Leetcode : Yes

import java.util.Arrays;

public class CoinChange_LC322 {
public int coinChange(int[] coins, int amount) {
//Handle empty input
if (coins == null || coins.length == 0 || amount == 0)
return 0;

//DP array to store amount
int[] dp = new int[amount + 1];
/**
* Approach 1 with 2D memoization
* Keep a 2D array that keeps track of min coins needed for each denomination to reach amount
* The answer will be located at last row and column of dp array
*/
/*int[][] dp = new int[coins.length + 1][amount + 1]; // DP array
for (int i = 0; i < coins.length + 1; i++) dp[i][0] = 0; // 0 coins used to reach 0 amount
for (int i = 0; i < amount + 1; i++) dp[0][i] = amount + 1; // infinite coins of 0 needed to reach amount
for (int i = 1; i < coins.length + 1; i++) {
for (int j = 1; j < amount + 1; j++) {
if (j < coins[i - 1]) // Denomination more than amount to be reached
dp[i][j] = dp[i - 1][j]; // Use previous subproblem's solution
else
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - coins[i - 1]] + 1); // take min of new soln vs prev subproblem soln
}
}
return dp[coins.length][amount] < amount + 1 ? dp[coins.length][amount] : -1; // value is inf, there's no soln*/

/**
* Approach 2 with 1D memoization; avoid 2D array since we need only one previous row for calculating subproblem's soln
* Keep a 1D array that keeps track of min coins needed to reach intermediate amountsØ
* The answer will be located at last index of dp array
*/
int[] dp = new int[amount + 1]; // DP array

for (int i = 0; i < amount + 1; i++) // Initialize array to infinity: amount + 1
dp[i] = amount + 1;

Arrays.fill(dp, amount + 1);
dp[0] = 0;
dp[0] = 0; // 0 coins used to reach 0 amount

for (int i = 1; i < amount + 1; i++) {
for (int j = 0; j < coins.length; j++)
if (coins[j] <= i)
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
for (int coin : coins) {
if (coin <= i)
dp[i] = Math.min(dp[i], 1 + dp[i - coin]);
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
Expand Down
36 changes: 26 additions & 10 deletions HouseRobber_LC198.java
Expand Up @@ -2,26 +2,42 @@
* Use Dynamic Programming memoization and initialize a dp array with size n+1
* such that ith index will correspond to stealing ith house
* 0th index: no house, 1st index: 1st house, ..., nth index: nth house
*
* <p>
* For maximizing dollars, go bottom up filling max stolen value at ith index of dp array
* At any point use previously calculated max robbed value and find maximum of including current house or including previous
*/

// Time Complexity: O (N)
// Space Complexity: O (N) due to memoization
// Space Complexity: O (1) due to memoization
// Did this code successfully run on Leetcode : Yes
public class HouseRobber_LC198 {
public int rob(int[] nums) {
if (nums == null || nums.length == 0) // Handling empty input
if (nums == null || nums.length == 0)
return 0;

int[] dp = new int[nums.length + 1]; // DP array
dp[0] = 0; // Stealing 0 houses
dp[1] = nums[0]; // Stealing 1st house
for (int i = 1; i < nums.length; i++) {
dp[i + 1] = Math.max(dp[i], dp[i - 1] + nums[i]); // Max of previous and including ith house or not
/** Approach 1 Using 1D DP array
* Keep filling DP array by taking current house and solution till that point into consideration
* Answer lies at last index of DP array
*/
/*int[] dp = new int[nums.length + 1]; // DP array
dp[0] = 0;
dp[1] = nums[0];
for (int i = 2; i <= nums.length; i++) {
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i - 1]); // Choose max between prev solution and previous to previous solution plus current house
}
return dp[nums.length];*/

/** Approach 2 without DP array
* At each house, you either choose it or don't
* Keep 2 varibles to keep track of maximum house amount robbed when house was chosen or when it wasn't
*/
int choose = 0, noChoose = 0;
for (int num : nums) {
int temp = noChoose;
noChoose = Math.max(choose, noChoose);
choose = temp + num;
}
// Last index will have maximum robbed value contributed by optimal at each step before
return dp[nums.length];
return Math.max(choose, noChoose);
}
}

0 comments on commit cae8560

Please sign in to comment.