Leetcode dynamic planning exercise

Dynamic programming algorithm design steps:

  1. Characterize the structural features of the optimal solution (to find the optimal substructure)
  2. Recursively define the optimal solution value (determined recursive formula, focusing on dynamic programming is this)
  3. Optimum value calculation (in two ways: with memo top-down method, bottom-up approach)
  4. Configuration information using the calculated an optimal solution (usually the optimal solution to a particular output)

Dynamic Programming Advanced ------>
git real-time updates

Best Time to Buy and Sell Stock

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Note that you cannot sell a stock before you buy one.

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.

solution:

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        # (1)暴力法,也是最容易想到的
        # maxResult = 0
        # for i in range(len(prices)):
        #     for j in range(len(prices)-i-1):
        #         if(prices[j+i+1]-prices[i] > maxResult):
        #             maxResult = prices[j+i+1]-prices[i]
        # return maxResult
        
        # (2)遍历一次
        minP = sys.maxint
        maxP = 0
        for i in range(len(prices)):
            if (prices[i] < minP):
                minP = prices[i]
            elif(prices[i] - minP > maxP):
                maxP = prices[i] - minP
        return (0 if maxP<0 else maxP)

Best Time to Buy and Sell Stock II

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times).

Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).

Example 1:
Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
             Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.
Example 2:
Input: [1,2,3,4,5]

Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.

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

solution: do not use or feel something dynamic programming, high long day behind the stock the day before, took profits in stocks added to gains

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        # 只要后面的股票价格比前一天高,就把利润添加到收益中。
        maxP = 0
        for i in range(len(prices)-1):
            if (prices[i+1]>prices[i]):
                maxP+=(prices[i+1]-prices[i])
        return maxP

Longest Palindromic Substring

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
Output: "bb"

solution: for the first time or the first thought is Violence Act (no restrictions by time), followed by another using a dynamic programming, but the running time is not very good, could be improved

dynamic programming steps:

Matrix DP initial values are 0

First initialize are provided on the (diagonal NP [i] [i] is 1, the elements on the diagonal to the center of the palindrome are odd length; the same two corresponding DP [i + 1] [i ]
palindromic element length is set to 1, this center two elements are even) ->

Alt

Looking then carried out on the basis of initialization ->

first assumed palindrome length of 3, after ascending order. If the two sides of the central characters are the same, it will come in plan, corresponding to the position of the DP is set to 1, the process used in performing the previous results, improve the efficiency to some extent.

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # 暴力法,总是最先想到的
        # def isRevrse(s):
        #     if(s==s[::-1]):
        #         return True
        #     else:
        #         return False
        # maxlen = 0
        # maxi = 0
        # for i in range(len(s)):
        #     for j in range(len(s)-i+1):
        #         if(isRevrse(s[i:i+j]) & (j > maxlen)):
        #             maxlen = j
        #             maxi = i
        # return s[maxi:maxi+maxlen]
        ### 动态规划一
        dp=[[0 for i in range(len(s))] for j in range(len(s))]
        maxLen = 1
        left = 0
        for i in range(len(s)): #初始化
            dp[i][i]=1
            left = i
        for i in range(len(s)-1): #初始化
            if s[i]==s[i+1]:
                dp[i][i+1]=1
                left = i
                maxLen = 2
        for l in range(3,len(s)+1,1):     # l表示当前要检测的字串串的长度
            for i in range(0,len(s)-l+1,1):  # i表示当前要检测的字符串的起始位置
                j = i + l -1                 # j表示当前要检测的字符串的尾位置
                if (dp[i+1][j-1]==1 and s[i]==s[j]):
                    dp[i][j] = 1
                    left = i
                    maxLen = l
        return s[left:left+maxLen]

Unique Paths

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).
How many possible unique paths are there?

Alt

Above is a 7 x 3 grid. How many possible unique paths are there?

Note: m and n will be at most 100.

Example 1:

Input: m = 3, n = 2
Output: 3
Explanation:
From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Right -> Down
2. Right -> Down -> Right
3. Down -> Right -> Right
Example 2:

Input: m = 7, n = 3
Output: 28

Solution: The first step to see the title, according to the dynamic programming ideas to think about.

Since the robot can walk to the right and down to the first row have a single lattice moves: dp [0] [] = 1, only reaches a first row in the grid moves: dp [] [0] = 1.

Then the number reaches a grid line, the grid line should be left together with the directions on the side of the grid and: dp [i] [j] = dp [i-1] [j] + dp [i] [j- 1].

But here we go to find the optimal solution, but to find all the solutions. Method memo.

class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        dp = [[0 for i in range(m)] for j in range(n)]
        for i in range(m):
            dp[0][i] = 1
        for i in range(n):
            dp[i][0] = 1
        for i in range(m-1):
            for j in range(n-1):
                dp[j+1][i+1] = dp[j+1][i]+dp[j][i+1]
        return dp[n-1][m-1]

Unique Paths II

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).

Now consider if some obstacles are added to the grids. How many unique paths would there be?

Alt

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

Note: m and n will be at most 100.

Example 1:

Input:
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
Output: 2
Explanation:
There is one obstacle in the middle of the 3x3 grid above.
There are two ways to reach the bottom-right corner:
1. Right -> Right -> Down -> Down
2. Down -> Down -> Right -> Right

Solution: difference between this road and I question is the subject with obstacles, but the basic idea is still the same.

Once the route is just the number of obstacles to be adopted this point of encounter barriers set to 0.

other thinking the same.

class Solution(object):
    def uniquePathsWithObstacles(self, obstacleGrid):
        """
        :type obstacleGrid: List[List[int]]
        :rtype: int
        """
        n = len(obstacleGrid)
        m = len(obstacleGrid[0])
        dp = [[0 for i in range(m)] for j in range(n)]
        for i in range(m):
            if(obstacleGrid[0][i]==1):
                break;
            dp[0][i] = 1
        for i in range(n):
            if(obstacleGrid[i][0]==1):
                break;
            dp[i][0] = 1
        for i in range(m-1):
            for j in range(n-1):
                if(obstacleGrid[j+1][i+1]==1):
                    continue;
                dp[j+1][i+1] = dp[j+1][i]+dp[j][i+1]
        return dp[n-1][m-1]

Minimum Path Sum

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

Example:

Input:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.

Solution: This problem is still the problem of dynamic programming, but that is Unique Paths and Unique PathsII an evolution, is the number of the previous two questions seeking the path, and this question is for the minimum of all paths, and in front of the subject relations have progressive layers.

dp [i] [j] the optimal solution: selecting the minimum value from the left side and the upper side, with a value corresponding to the present point, that is, reaches a minimum value of the present point: dp [j + 1] [ i + 1 ] = min (dp [j] [i + 1], dp [j + 1] [i]) + grid [j + 1] [i + 1]

is defined recursively the optimal solution: the value of each point dp , it is minimum.

method: memo top-down,

the output of the optimal solution.

Dp foregoing for recording the number of paths, where dp is used to record the minimum value reaches dp [i] [j], and

class Solution(object):
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        n = len(grid)	#行数
        m = len(grid[0])	#列数
        dp = [[0 for i in range(m)] for j in range(n)]
        dp[0][0] = grid[0][0]
        for i in range(m-1):
            dp[0][i+1] = grid[0][i+1]+dp[0][i]
        for i in range(n-1):
            dp[i+1][0] = grid[i+1][0]+dp[i][0]
        for i in range(m-1):
            for j in range(n-1):
                dp[j+1][i+1] = min(dp[j][i+1],dp[j+1][i])+grid[j+1][i+1]
        return dp[n-1][m-1]

The following is submitted with the shortest time program can be seen that he is operating directly on the grid, so when using the above shorter than me.

class Solution(object):
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        if grid is None:
            return 0
        rows = len(grid)
        cols = len(grid[0])
        if cols == 0:
            return 0
        
        for i in range(1, cols):
            grid[0][i] += grid[0][i - 1]
        for i in range(1, rows):
            grid[i][0] += grid[i - 1][0]
        for i in range(1, rows):
            for j in range(1, cols):
                grid[i][j] += min(grid[i - 1][j], grid[i][j - 1])
        return grid[-1][-1]

Maximum Subarray

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

solution: look at this question a long time ago when the purpose is solved by violence law, but is not limited by the time. Dynamic programming is a recent practice with a little bit of sense to the solution of this question once again.
This issue has been discussed by the Jon Bentley (September 1984 Volume 27, No. 9 ACM P885 communication)
The following is the text:

the paragraph below was copied from his paper (with a little modifications)

algorithm that operates on arrays: it starts at the left end (element A[1]) and scans through to the right end (element A[n]), keeping track of the maximum sum subvector seen so far. The maximum is initially A[0]. Suppose we've solved the problem for A[1 .. i - 1]; how can we extend that to A[1 .. i]? The maximum
sum in the first I elements is either the maximum sum in the first i - 1 elements (which we'll call MaxSoFar), or it is that of a subvector that ends in position i (which we'll call MaxEndingHere).

MaxEndingHere is either A[i] plus the previous MaxEndingHere, or just A[i], whichever is larger.

Local optimal substructure: comprises a maximum time and the last element of string,
the value of the optimal solution: MaxSofar = max (MaxSofar, MaxEnd ) {MaxEnd = max (MaxEnd + nums [i], nums [i]), ManEnd It can be considered as the optimal solution when the auxiliary optimal substructure}, MaxSofar is the target, when the first element is MaxEnd traversed up to the i-th element from the first element to the i-th element of the i-th element contains . (I-th element contains the latter traverse convenient, because most questions asked sequence is continuous, if the latter does not traverse the i-th element after the element inconvenient to be traversed containing)
calculated optimal solution: bottom-up
most An optimum solution: maximum output MaxSofar

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        count = len(nums)
        if count==0:
            return 0
        MaxEnd = nums[0]
        MaxSof = nums[0]
        for i in range(count-1):
            MaxEnd = max(MaxEnd+nums[i+1],nums[i+1])
            MaxSof = max(MaxSof,MaxEnd)
        return MaxSof
class Solution(object):
    def maxSubArray(self, nums):
        # 下面和上面的思路时一样的,但是更加简洁高效
        count = len(nums)
        for i in range(1,count):
            if nums[i-1] > 0:
                nums[i] = nums[i] + nums[i-1]
        return max(nums)

Guess you like

Origin blog.csdn.net/li123_123_/article/details/84890591