Dynamic programming method (leetcode classic case analysis)

Time:2020-5-27

Today, let’s summarize some classic topics about dynamic planning on leetcode:

  • Best time to buy and sell stock
  • House robber (maximum amount of robbery)
  • Integer break
  • Minimum path sum
  • Triangle

Best time to buy and sell stock

Title: if you are only allowed to complete one transaction at most (i.e. buy one share, sell one share), design an algorithm to find the maximum profit

Example 1:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.

Example 2:
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

code implementation

public int maxProfit(int[] prices) {
    
    int ans = 0;
    if (prices.length == 0) {
        return ans;
    }
    
    int bought = prices[0];
    for (int i = 1; i < prices.length; i++) {
        if (prices[i] > bought) {
            if (ans < (prices[i] - bought)) {
                Ans = prices [i] - right; // find the maximum profit
            }
        } else {
            Bought = prices [i]; // find the minimum cost
        }
    }
    return ans;
}

House robber (maximum amount of robbery)

Title: given an array of integers to represent a series of consecutive houses with money in them, the maximum amount that can be grabbed can be found when the adjacent houses cannot be entered consecutively to grab money.
Example :
Input: [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.

Solutions to problems

  1. There is only one house nums [0], the maximum income is DP [0] = nums [0];
  2. There are two houses, nums [0], nums [1], which cannot be taken at the same time. The maximum income is DP [1] = max (nums [0], nums [1]);
  3. There are three houses with two methods: nums [1], or nums [0] and nums [2]. That is DP [2] = max (nums [1], nums [0] + nums [2]);
  4. Therefore, it can be inferred that the dynamic conversion equation is:dp[i] = max(nums[i] + dp[i-2], dp[i-1]);

code implementation

public static int rob(int[] nums) {

    if (nums == null ||  nums.length  ==0) throw new runtimeException ("illegal input");
    if (nums.length == 1) return nums[0];
    if (nums.length == 2) return nums[1] > nums[0] ? nums[1] : nums[0];

    int n = nums.length;
    int[] rob = new int[n];
    //Initialize rob [0] and rob [1]
    rob[0] = nums[0];
    rob[1] = nums[1] > nums[0] ? nums[1] : nums[0];
    //Equation: DP [i] = max (nums [i] + DP [I-2], DP [I-1])
    for (int i = 2; i < n; i++) {
        rob[i] = rob[i - 1] > rob[i - 2] + nums[i] ? rob[i - 1] : rob[i - 2] + nums[i];
    }
    return rob[n - 1];
    }
}

Integer break

Title: divide a number into the sum of several positive integers, and find the maximum value of the product of these positive integers
Input: 10
Output: 36
Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36.

code implementation

class Solution {
    //Dynamic planning: bottom-up
    public static int integerBreak(int n) {
        //Condition judgment
        if (n <= 0) 
             Throw new runtimeException ("illegal input");
        int[] dp = new int[n + 1];
        Arrays.fill(dp, -1);
        dp[1] = 1;
        //Calculate the value of DP [2] ~ DP [n]
        for (int i = 2; i <= n; i++) {
            //J means there are 1 ~ n-1 cutting methods (the first section is cut into [1, n-1], [2, n-2]... [n-1, 1])
            for (int j = 1; j < i - 1; j++) {
                dp[i] = max3(dp[i], j * (i - j), j * dp[i - j]);
            }
        }
        return dp[n];
    }
    //Returns the maximum of three numbers
    private static int max3(int a, int b, int c) {
        return Math.max(Math.max(a, b), c);
    }
}

Minimum path sum

Topic: given a two-dimensional array, starting from the upper left corner, you can only move down or right each time to find the shortest path sum from the upper left corner to the lower right corner.
Input:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.

Solutions to problems

1. If we are in the grid at the bottom right corner (it can also be imagined that the grid has only one grid), then the shortest path sum is the value in the grid
2. If we are in the last line, if we are row-1, then the minimum path sum from this point to the bottom right corner is the sum of the minimum path itself plus the lattice on its right to the bottom right corner
3. The last column and the last row are the same
4. For a common position, what is the minimum path sum to the bottom right corner? It is the minimum path sum of the right position and the bottom position plus its own value

code implementation

public static int dpMinPath(int[][] a) {
        //Condition judgment
        if (a == null || a.length == 0 || a[0].length == 0) {
            Throw new runtimeException ("illegal input! "";
        }
         int row = a.length;
        int col = a[0].length;
        
        //DP [i] [J] represents the shortest path from a [i] [J] to the lower right corner and
        int dp[][] = new int[row][col];
        dp[0][0] = a[0][0];
        //Fill first column
        for (int i = 1; i < row; i++) {
            dp[i][0] = a[i][0] + dp[i - 1][0];
        }
        //Fill first line
        for (int i = 1; i < col; i++) {
            dp[0][i] = a[0][i] + dp[0][i - 1];
        }
        //Others
        for (int i = 1; i < row; i++) {
            for (int j = 1; j < col; j++) {
                dp[i][j] = a[i][j] + Math.min(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        return dp[row - 1][col - 1];
    }
}

Triangle

Topic: given a triangle, find the minimum path sum from top to bottom. You can move to each step of the adjacent number in the next row.
For example, given the following triangle

    [2]
   [3,4]
  [6,5,7]
 [4,1,8,3]

The minimum path sum from top to bottom is 11 ( 2 + 3 + 5 + 1 = 11).

code implementation

public static int minimumTotal(List<List<Integer>> triangle) {
        //Condition judgment
        if (triangle == null || triangle.size() == 0)  return 0;
        if (triangle.size() == 1) return triangle.get(0).get(0);

        int[] dp = new int[triangle.size()];
        //Traverse up from the last line
        for (int i = triangle.size() - 1; i >= 0; i--) {
            for (int j = 0; j < triangle.get(i).size(); j++) {
                //DP [J] in the last line is the corresponding value
                if (i == triangle.size() - 1) {
                    dp[j] = triangle.get(i).get(j);
                } else {
                    //Starting from the penultimate row, DP [J] = the smaller of the lower left DP value and the lower right DP value + its own value
                    dp[j] = Math.min(dp[j], dp[j + 1]) + triangle.get(i).get(j);
                }
            }
        }
        return dp[0];
   }

Recommended Today

Swift advanced (XV) extension

The extension in swift is somewhat similar to the category in OC Extension can beenumeration、structural morphology、class、agreementAdd new features□ you can add methods, calculation attributes, subscripts, (convenient) initializers, nested types, protocols, etc What extensions can’t do:□ original functions cannot be overwritten□ you cannot add storage attributes or add attribute observers to existing attributes□ cannot add parent […]