Some exercises of dynamic programming

Posted by nagrgk on Mon, 21 Feb 2022 07:31:36 +0100

1. Change

subject

class Solution {
    public int coinChange(int[] coins, int amount) {
        int n = coins.length;
        int[] arr = new int[amount + 1];// 0..amount

        // Define initial conditions
        arr[0] = 0;
        for(int i = 1; i <= amount; i++) {
            // Find arr[i]
            arr[i] = Integer.MAX_VALUE;
            for(int j = 0; j < n; j++) {
                if(i >= coins[j] && arr[i - coins[j]] != Integer.MAX_VALUE && arr[i - coins[j]] + 1 < arr[i]) {
                    arr[i] = arr[i - coins[j]] + 1;
                }

            }
        }
        if (arr[amount] == Integer.MAX_VALUE) {
            return -1;
        }else {
            return arr[amount];
        }
        

    }
}

2. Different paths - 1

subject

analysis:

The first step of dynamic planning: determine the status

a. The last step: no matter how the robot finally reaches the end, there are only two cases in the last step, that is, from left to right and from top to bottom. If the target position is [m - 1][n -1], it comes from [m-2][n-1] and [m - 1][n - 2].
b. Subproblem. The original problem is from [0] [0] to [m-1][n-1] into how many ways from [0] [0] to [m-2][n-1] and how many ways from [0] [0] to [m-1][n-2]

The second step of dynamic programming: state transition equation

f[i][j] = f[i - 1][j] + f[i][j - 1]

The third step of dynamic programming: initial conditions and boundary conditions

Initial condition: f[0][0] = 1
Boundary condition: when i = 0 or j = 0, you can only come from one direction, f [0] [J] = 1, f [i] [0] = 1

Step 4 of dynamic programming: calculation sequence

Calculate row 0
Calculate line 1
. . .
Calculate line m - 1
The answer is f[m - 1][n -1]

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] arr = new int[m][n];
        arr[0][0] = 1;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if (i == 0 || j == 0) {
                    arr[i][j] = 1;
                }else{
                    arr[i][j] = arr[i][j - 1] + arr[i - 1][j];         
                }
                      
        }
    }
    return arr[m - 1][n - 1];
    }
}

3. Different paths - 2

subject

Analysis: the difference between this question and 1 is that the obstacle f[i][j] = 0, and then in the boundary conditions, the uppermost and leftmost are no longer directly equal to 1, but determined by the one in front of it!

The first step of dynamic planning: determine the status

a. The last step: no matter how the robot finally reaches the end, there are only two cases in the last step, that is, from left to right and from top to bottom. If the target position is [m - 1][n -1], it comes from [m-2][n-1] and [m - 1][n - 2].
b. Subproblem, the original problem is to change from [0] [0] to [m-1][n-1] into how many ways from [0] [0] to [m-2][n-1] and how many ways from [0] [0] to [m-1][n-2]

The second step of dynamic programming: state transition equation

f[i][j] = f[i - 1][j] + f[i][j - 1]

The third step of dynamic programming: initial conditions and boundary conditions

Initial condition: f[0][0] = 1
Boundary conditions: i = 0 or j = 0, f [i] [J] = f [i] [J - 1] or f[i - 1][j]

Step 4 of dynamic programming: calculation sequence

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[][] arr = new int[m][n];
        if(obstacleGrid[0][0] == 1 || obstacleGrid[m - 1][n - 1] == 1) {
            return 0;
        }else{
            arr[0][0] = 1;
            for(int i = 0; i < m; i++) {
                for(int j = 0; j < n; j++) {
                    if(obstacleGrid[i][j] == 1) {
                        arr[i][j] = 0;
                    }else{
                        if(i == 0 && j == 0){
                            arr[i][j] = 1;
                        }else{
                            if(i == 0) {
                                arr[i][j] = arr[i][j - 1];
                            }
                            if(j == 0) {
                                arr[i][j] = arr[i - 1][j];
                            }
                            if(i != 0 && j != 0) {
                                arr[i][j] = arr[i - 1][j]+ arr[i][j - 1];
                            }
                        }
                    }
                }
            }
        }

        return arr[m - 1][n - 1];
    }
}

4. Jumping game

subject

analysis:

The first step of dynamic planning: determine the status

a. The last step: no matter how you get to the last step, you will jump directly from the previous step
b. For the subproblem, it can jump to the last step j successfully. The last jump is successful in position i, and the number of steps that can jump in position i can reach j

The second step of dynamic programming: state transition equation

f[j] = or{i = 0 to J-1} {f [i] & & nums [i] > J - I}

The third step of dynamic programming: initial conditions and boundary conditions

Initial condition: f[0]= true
Boundary conditions: None

Step 4 of dynamic programming: calculation sequence

From small to large.

class Solution {
    public boolean canJump(int[] nums) {
        // There are two conditions for f[j] to be true
        // 1. f[i] = true 2. nums[i] > j - i
        if (nums == null || nums.length == 0) return false;
        int n = nums.length;
        boolean[] arr = new boolean[n+1];
        arr[0] = true;
        

        for(int i = 1; i < n; i++) {
            
            arr[i] = false; // Here is a small detail
            for(int j = 0; j < i; j++) {
                if(arr[j] && nums[j] >= i - j) {
                    arr[i] = true;
                    break;
                }
            }
           
        }
        return arr[n - 1];
    }
}

5. Paint the house

Paint the house 2. Please move to question 12
subject
analysis:
Sequential dynamic programming: first i minimum / number of modes / minimum
sequence ➕ state

class Solution {
    public int minCost(int[][] costs) {
        int n = costs.length;// Number of houses
        int[][] arr = new int[3][n];
        //arr[0][i] represents the lowest price of the first I house when the I house is red
        // arr[1][i] represents the lowest price of the first I house when the I house is blue
        // arr[2][i] represents the lowest price of the first I house when the I house is green

        // initial condition 
        for(int i = 0; i < 3; i++) {
            arr[i][0] = costs[0][i];
        }
        for(int i = 1; i < n; i ++) {
            arr[0][i] = arr[1][i - 1] > arr[2][i - 1] ? arr[2][i - 1] + costs[i][0]: arr[1][i - 1] + costs[i][0];
            arr[1][i] = arr[0][i - 1] > arr[2][i - 1] ? arr[2][i - 1] + costs[i][1]: arr[0][i - 1] + costs[i][1];
            arr[2][i] = arr[0][i - 1] > arr[1][i - 1] ? arr[1][i - 1] + costs[i][2]: arr[0][i - 1] + costs[i][2];
        }
        return getMin(arr[0][n - 1], arr[1][n - 1], arr[2][n - 1]);

        
    }
    public int getMin(int a, int b, int c) {
        int temp = a>b?b:a;
        return temp>c?c:temp;
    }

}

6. Decoding method

subject

My solution is very verbose

class Solution {
    public int numDecodings(String s) {
        if(s == null || s.charAt(0) == '0') {
            return 0;
        }else if(s.length() == 1 && s.charAt(0) != '0' ) {
            return 1;
        }else{
            int n = s.length();
            int[] arr = new int[n];
            arr[0] = 1;
           
            if(s.charAt(0) == '1' && s.charAt(1) != '0') {
                    // If the first one is 1 or 2
                    arr[1] = 2;
                }else if(s.charAt(0) == '2'&& Character.getNumericValue(s.charAt(1)) <= 6 && s.charAt(1) != '0') {
                   arr[1] = 2; 
                }else if(Character.getNumericValue(s.charAt(0))>= 3&& s.charAt(1) == '0') {
                    // arr[1] = 0;
                    return 0;
                }else if(s.charAt(0) == '0'&& s.charAt(1) == '0') {
                    return 0;
                }
                else{
                    arr[1] = 1;
                }
            for(int i = 2; i < n; i++){
                if(s.charAt(i - 1) == '1' && s.charAt(i) != '0') {
                    // If the first one is 1 or 2
                    arr[i] = arr[i - 1] + arr[i - 2];
                }else if(Character.getNumericValue(s.charAt(i - 1))>= 3 && s.charAt(i) == '0') {
                    // arr[1] = 0;
                    return 0;
                }else if(s.charAt(i - 1) == '0' && s.charAt(i) == '0') {
                    return 0;
                }
                else if(s.charAt(i - 1) == '2' && Character.getNumericValue(s.charAt(i)) <= 6 && s.charAt(i) != '0') {
                   arr[i] = arr[i - 1] + arr[i - 2];
                }else if(s.charAt(i - 1) == '1' && s.charAt(i) == '0'){
                   arr[i] = arr[i - 2];
                }else if (s.charAt(i - 1) == '2' && s.charAt(i) == '0'){
                    arr[i] = arr[i - 2];
                }else{
                    arr[i] = arr[i - 1];
                }
            }

            return arr[n - 1];
        }
            
        
    }
}

A relatively simple and skilled solution

class Solution {
    public int numDecodings(String s) {
        char[] ss = s.toCharArray();
        int n = ss.length;
        if (n == 0) {
            return 0;
        }
        int[] arr = new int[n+1];
        int m = ss[0] - '0';
        arr[0] = 1;
        for(int i = 1; i <= n; i++) {
            arr[i] = 0;
            int t = ss[i - 1] - '0';
            if(t >= 1 && t <= 9){
                arr[i] += arr[i - 1];
            }
            if(i >= 2) {
                int q = ss[i - 2] - '0';
                int p = ss[i - 1] - '0';
                if(q * 10 + p >= 10 && q * 10 + p <= 26) {
                    arr[i] += arr[i - 2];// Learn well and wait
                }
            }
            
            
        }
        return arr[n];
        
    }
}

7. Longest continuous increasing subsequence

Coordinate dynamic programming
subject

class Solution {
    public int findLengthOfLCIS(int[] nums) {
        int n = nums.length;
        if(n == 0) {
            return 0;
        }else{
            int[] arr = new int[n];
            arr[0] = 1;
            int m = 1;
            for(int i = 1;i < n; i++) {
                if(nums[i]> nums[i - 1]){
                    arr[i] = arr[i - 1] + 1;
                }else{
                    arr[i] = 1;
                }
                if(m <= arr[i]){
                    m = arr[i];
                }
            }
            return m;
        }
        

    }
}

8. Minimum path and

subject

class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int[][] arr = new int[m][n];
        arr[0][0] = grid[0][0];
        for(int i = 1; i < m; i++) {
            arr[i][0] = arr[i - 1][0] + grid[i][0];
        }
        for(int i = 1; i < n; i++) {
            arr[0][i] = arr[0][i - 1] + grid[0][i];
        }

        for(int i = 1; i < m; i++) {
            for(int j = 1; j < n; j++) {
                arr[i][j] = arr[i - 1][j] < arr[i][j - 1] ? grid[i][j] + arr[i - 1][j]: grid[i][j] + arr[i][j - 1];
            }
        }
        return arr[m - 1][n - 1];

    }
}

9. Bomb the enemy

subject

public static int maxKillEnemies(char[][] A) {
    if (A == null || A.length == 0 || A[0].length == 0) {
      return 0;
    }
    int m = A.length;
    int n = A[0].length;

    int[][] f = new int[m][n];
    int[][] res = new int[m][n];

    for (int i = 0; i < m; i++) {
      for (int j = 0; j < n; j++) {
        res[i][j] = 0;
      }
    }

    // up
    for (int i = 0; i < m; i++) {
      for (int j = 0; j < n; j++) {
        if (A[i][j] == 'W') {
          f[i][j] = 0;
        }else {
          f[i][j] = 0;
          if (A[i][j] == 'E') {
            f[i][j] = 1;
          }
          if (i > 0) {
            f[i][j] += f[i - 1][j];
          }
        }
        res[i][j] += f[i][j];
      }
    }

    // down
    for (int i = m - 1; i >= 0; i--) {
      for (int j = n - 1; j >= 0; j--) {
        if (A[i][j] == 'W') {
          f[i][j] = 0;
        }else {
          f[i][j] = 0;
          if (A[i][j] == 'E') {
            f[i][j] = 1;
          }
          if (i < m - 1) {
            f[i][j] += f[i + 1][j];
          }
        }
        res[i][j] += f[i][j];
      }
    }

    // left
    for (int i = 0; i < m; i++) {
      for (int j = 0; j < n; j++) {
        if (A[i][j] == 'W') {
          f[i][j] = 0;
        }else {
          f[i][j] = 0;
          if (A[i][j] == 'E') {
            f[i][j] = 1;
          }
          if (j > 0) {
            f[i][j] += f[i][j - 1];
          }
        }
        res[i][j] += f[i][j];
      }
    }

    // right
    for (int i = 0; i < m; i++) {
      for (int j = n - 1; j >= 0; j--) {
        if (A[i][j] == 'W') {
          f[i][j] = 0;
        }else {
          f[i][j] = 0;
          if (A[i][j] == 'E') {
            f[i][j] = 1;
          }
          if (j < n - 1) {
            f[i][j] += f[i][j + 1];
          }
        }
        res[i][j] += f[i][j];
      }
    }
    int result = Integer.MIN_VALUE;

    for (int i = 0; i < m; i++) {
      for (int j = 0; j < n; j++) {
        if (A[i][j] == '0') {
          result = result > res[i][j] ? result:res[i][j];
        }
      }

    }

    return result;
  }

10. Yang Hui triangle

subject

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> dp = new ArrayList<List<Integer>>();
        List<Integer> tmp = new ArrayList<Integer>();
        tmp.add(1);
        dp.add(tmp);
        if(numRows == 1) {
            return dp;
        }
        List<Integer> tmp2 = new ArrayList<Integer>();
            tmp2.add(1);
            tmp2.add(1);
            dp.add(tmp2);
        if(numRows == 2) {
            return dp;
        }
        

        for(int i = 2; i < numRows; i++) {
            List<Integer> t = new ArrayList<Integer>();
            t.add(1);
            for(int j = 1; j < i; j++) {
                t.add(dp.get(i - 1).get(j - 1) + dp.get(i - 1).get(j));
            }
            t.add(1);
            dp.add(t);
        }
        return dp;
    }
}

11. Bit count

subject

class Solution {
    public int[] countBits(int n) {
        if(n == 0) {
            return new int[]{0};
        }else{
            int[] dp = new int[n + 1];
            dp[0] = 0;
            dp[1] = 1;
            for(int i = 2; i <= n; i++) {
                dp[i] = dp[i >> 1] + i % 2;
            }
            return dp;
        }

    }
}

12. Painting the house 2

subject

class Solution {
    public int minCostII(int[][] costs) {
        int n = costs.length; // n houses
        int k = costs[0].length; // k colors
        int[][] f = new int[n+1][k];
        int min1, min2;
        int j1 = 0;
        int j2 = 0;
        
        // dp[i][j] I house before painting, and i-1 house is the minimum cost of j color
        for(int j = 0; j < k; j++) {
            f[0][j] = 0;
        }
        for(int i = 1; i <= n; i++) {
            //Minimum and sub minimum
            min1 = min2 = Integer.MAX_VALUE;
            for(int j = 0; j < k; j++) {
                if(f[i - 1][j] < min1) {
                    min2 = min1;
                    j2 = j1;
                    min1 = f[i - 1][j];
                    j1 = j;
                }else{
                    if(f[i - 1][j] < min2) {
                        min2 = f[i - 1][j];
                        j2 = j;
                    }
                }
            } 
            for(int j = 0; j < k; j++) {
                if(j == j1) {
                    f[i][j] = costs[i - 1][j] + min2;
                }else{
                    f[i][j] = costs[i - 1][j] + min1;
                }
            }         
        } 
        int res = Integer.MAX_VALUE;
        for(int i = 0; i < k; i++) {
            res = res < f[n][i] ? res : f[n][i];
        }
        return res;   
    }
}

13. House theft

subject

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        if(n == 1){
            return nums[0];
        }else if(n == 2){
            return Math.max(nums[0], nums[1]);
        }else{
            int[] f = new int[n];
            f[0] = nums[0];
            f[1] = Math.max(nums[0], nums[1]);
            for(int i = 2; i < n; i++) {
                f[i] = f[i - 2] + nums[i] > f[i - 1] ? f[i - 2] + nums[i] : f[i - 1];
            }
            return f[n - 1];

        }
    }
}

14. House theft 2

subject

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        if (n == 1) {
            return nums[0];
        }else if(n == 2) {
            return Math.max(nums[0], nums[1]);
        }else if(n == 3){
            return Math.max(nums[0], Math.max(nums[1], nums[2]));
        }else{
            int[][] f = new int[n][2];
            f[0][0] = nums[0];
            f[0][1] = 0;
            f[1][0] = nums[0];
            f[1][1] = nums[1];
            f[2][0] = nums[0];
            f[2][1] = Math.max(nums[1], nums[2]);

            for(int i = 3; i < n; i++) {
                f[i][0] = Math.max(f[i - 1][0], f[i - 2][0]+ nums[i - 1]); 
                f[i][1] = Math.max(f[i - 1][1], f[i - 2][1]+ nums[i]); 
            }
            return Math.max(f[n - 1][0], f[n - 1][1]);
        }
           
    }
}

15. Maximum profit of shares

subject

class Solution {
    public int maxProfit(int[] prices) {
        int n = prices.length;

        if(n <= 1) {
            return 0;
        }else {
            int[] dp = new int[n];
            dp[0] = 0;
            int tmp = prices[0];
            for(int i = 1; i < n; i++) {
                if(tmp > prices[i]){
                    tmp = prices[i];
                }
                if(prices[i] < prices[i - 1]){
                    dp[i] = dp[i - 1];
                }else{
                    dp[i] = Math.max(prices[i] - tmp, dp[i - 1]);
                }
            }
            return dp[n - 1];
        }

    }
}

Topics: Algorithm Dynamic Programming