Dynamic Programming Flashcards

1
Q
  1. Climbing Stairs

You are climbing a staircase. It takes n steps to reach the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

A
public int climbStairs(int n) {
        // the number of distinct ways we can go from one step to another is
        // by a single step (1) or double step (2)
        // so to get to step 5 you need to know the possible ways to get step 3
        // and the possible ways to get to 4, adding + 2 and + 1 to those gets you 
        // to step 5 from those.
        // ex. 3, to get to step 1, we have 1.  to get to step 3, we go 1 + 2
        // to get to step 2 we have 1 + 1 and 2, so you add 1 -> 1 + 1 + 1, 2 + 1
        // we only need the output though so we just can take those numbers and that 
        // is the actual number to get to the result
        if (n == 1) {
            return n;
        }
        // cache used to hold calculated values
        int[] dp = new int[n+1];
        dp[1] = 1;
        dp[2] = 2;
        // ^ you can actuall just use the number of steps away as 2 variables to hold these values
        // we only need the prev 2 to figure out how to get there
        for( int i = 3; i <= n; i++) {
            dp[i] = dp[i-1] + dp[i-2];
        }
        // only want numnber of steps to n
        return dp[n];
    }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q
  1. Coin Change

You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.

Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.

You may assume that you have an infinite number of each kind of coin.

A
public int coinChange(int[] coins, int amount) {
         // solve each amout up to amount, if we can't solve amount return -1
        int[] dp = new int[amount + 1]; // 0 indexed going to amount itself
        // initalize dp w/ unreliable value
        Arrays.fill(dp, amount + 1);
        // 0 is 0 coins
        dp[0] = 0;
        // for each amount find the min number of coins to make it
        for (int i = 1; i <= amount; i++) {
            for (int j = 0; j < coins.length; j++) {
                // check to see if our coin is less than i
                if (coins[j] <= i) {
                    // we can take this coin in 
                    dp[i] = Math.min(dp[i], 1 + dp[i - coins[j]]);
                    // ^ we take the current min, or 1 coin + the number of coins to make up the previous calculated amount.  So, if you have 4 coins in dp[5], you are on coin 2, so you check at position 3 to see if adding a coin to that is less than what we have.
                }
            }
        }
        return dp[amount] == amount + 1 ? -1 : dp[amount];
    }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q
  1. Longest Increasing Subsequence

Given an integer array nums, return the length of the longest strictly increasing subsequence.

A subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7].

A
public int lengthOfLIS(int[] nums) {
        // dp array to keep track of subsequences leading to nums.length
        int[] dp = new int[nums.length];
        Arrays.fill(dp, 1); // All index's are increasing subsequences of length 1
        // check subsequence for each pos
        for (int i = 1; i < nums.length; i++) {
            for (int j = 0; j < i; j++) {
                 if (nums[i] > nums[j] && dp[i] <= dp[j]) {
                     dp[i] = dp[j] + 1;
                 }
            }
        }
        return Arrays.stream(dp).max().getAsInt();
    }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q
  1. Word Break

Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.

Note that the same word in the dictionary may be reused multiple times in the segmentation.

A
// Dynamic Programming Problem since its solving smaller problems
    public boolean wordBreak(String s, List wordDict) {
        int n = s.length();
        int maxLength = 0;
        for (String word : wordDict) {
            maxLength = Math.max(maxLength, word.length());
        }
        // solve for word of length 1 up to s length
        // store temp states, we are checking each letter if it works
        // all values default false in java
        boolean[] dp = new boolean[n + 1];
        dp[0] = true; // "" is true in any dictionary
        // left and right pointers
        for (int i = 0; i <= n; i++) {
            for (int j = i - 1; j >= 0; j--) {
                if (i - j > maxLength) {
                    continue;
                }
                if (dp[j] && wordDict.contains(s.substring(j, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }   
    return dp[n];
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q
  1. House Robber

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.

Example 1:

Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
Example 2:

Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.

A
public int rob(int[] nums) {
        // edge cases
        if (nums == null || nums.length == 0) {
            return 0;
        }
    if (nums.length == 1) {
        return nums[0];
    }

    if (nums.length == 2) {
        return Math.max(nums[0], nums[1]);
    }
        // Actual Algorithm
        int[] dp = new int[nums.length]; // 0'd
        Arrays.fill(dp, -1);
        dp[0] = nums[0]; // one house is correct
        dp[1] = Math.max(nums[0], nums[1]);
        // loop
        for (int i = 2; i < dp.length; i++) {
            dp[i] = Math.max(dp[i-2] + nums[i], dp[i-1]);
        }
    return dp[nums.length-1];

}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly