# LeetCode problem brushing -- dynamic programming (python language)

# 1, Dynamic programming

## 1.1 basic concepts

Dynamic programming algorithms are usually used to solve problems with some optimal properties. In such problems, there may be many feasible solutions. Each solution corresponds to a value. We want to find the solution with the optimal value. The dynamic programming algorithm is similar to the divide and conquer method. Its basic idea is to decompose the problem to be solved into several sub problems. First solve the sub problems, and then get the solution of the original problem from the solutions of these sub problems.

## 1.2 algorithm steps

1. Confirmation status is generally the core content of the required solution of the problem, and can be divided into several sub problems.

2. Determine the state transition equation and list the change from one state to another, which is usually discussed in different cases.

3. Determine the initial value and the value of the initial state. Generally, take the special value or the first value of the array.

4. The order in which dynamic programming is carried out.

# 2, Brush questions

## 2.1 maximum subarray and

Give you an integer array nums. Please find a continuous sub array with the largest sum (the sub array contains at least one element) and return its maximum sum.

A subarray is a contiguous part of an array.

Example 1:

Input: num = [- 2,1, - 3,4, - 1,2,1, - 5,4]

Output: 6

Explanation: the maximum sum of continuous subarray [4, - 1,2,1] is 6.

Example 2:

Input: num = [1]

Output: 1

Example 3:

Input: num = [5,4, - 1,7,8]

Output: 23

Tips:

1 <= nums.length <= 105

-104 <= nums[i] <= 104

Advanced: if you have implemented a solution with complexity O(n), try using a more sophisticated divide and conquer method.

**Solution: * * determine the state and state transition equation, initial value and order according to the basic idea of dynamic programming. It mainly updates opt

class Solution: def maxSubArray(self, nums: List[int]) -> int: opt = [nums[0] if nums else None] for i in nums[1:]: opt.append(max(opt[-1]+i,i)) return max(opt)

## 2.2 longest common subsequence

Determine two strings text1 and text2, and return the length of the longest common subsequence of the two strings. If there is no common subsequence, 0 is returned.

The subsequence of a string refers to such a new string: it is a new string composed of the original string after deleting some characters (or not deleting any characters) without changing the relative order of characters.

For example, "ace" is a subsequence of "abcde", but "aec" is not a subsequence of "abcde".

The common subsequence of two strings is the subsequence shared by the two strings.

Example 1:

Input: text1 = "abcde", text2 = "ace"

Output: 3

Explanation: the longest common subsequence is "ace", and its length is 3.

Example 2:

Input: text1 = "abc", text2 = "abc"

Output: 3

Explanation: the longest common subsequence is "abc", and its length is 3.

Example 3:

Input: text1 = "abc", text2 = "def"

Output: 0

Explanation: two strings have no common subsequence and return 0.

Tips:

1 <= text1.length, text2.length <= 1000

text1 and text2 consist of lowercase English characters only.

**Solution: * * according to the idea of dynamic programming, set a two-dimensional matrix, traverse the two strings respectively, and add 1 to the same, otherwise i-1 or j-1 takes the maximum value.

class Solution: def longestCommonSubsequence(self, text1: str, text2: str) -> int: len1,len2 = len(text1),len(text2) opt = [[0 for i in range(len2+1)] for i in range(len1+1)] for i in range(len1): for j in range(len2): if(text1[i]==text2[j]): opt[i+1][j+1] = opt[i][j] + 1 else: opt[i+1][j+1] = max(opt[i+1][j],opt[i][j+1]) return opt[len1][len2]

## 2.3 longest palindrome subsequence

Give you a string s, find the longest palindrome subsequence, and return the length of the sequence.

Subsequence is defined as a sequence formed by deleting some characters or not deleting any characters without changing the order of the remaining characters.

Example 1:

Enter: s = "bbbab"

Output: 4

Explanation: one possible longest palindrome subsequence is "bbbb".

Example 2:

Enter: s = "cbbd"

Output: 2

Explanation: one possible longest palindrome subsequence is "bb".

Tips:

1 <= s.length <= 1000

s consists of lowercase English letters only

**Solution 1: * * invert the string, and the problem is transformed into the longest common subsequence of two strings

class Solution: def longestPalindromeSubseq(self, s: str) -> int: #Dynamic programming consists of four steps: inverting the string to determine the longest common subsequence, that is, the longest palindrome subsequence #1. Confirmation status: opt[j] stores [0:j], that is, the longest palindrome subsequence #2. Determine the state transition equation: t[i]==t[j] match + 1, otherwise return the maximum value of i-1 or j-1 #3. The initial condition opt[0][0]=0 is an empty string. The end condition is that the string traversal is completed. #4. Sequence, i from 1 to N, j from 1 to n. Remember that opt is [n+1][n+1] n = len(s) opt = [[0 for i in range(n+1)] for i in range(n+1)] ss = s[::-1] for i in range(n): for j in range(n): if(s[i]==ss[j]): opt[i+1][j+1] = opt[i][j] + 1 else: opt[i+1][j+1] = max(opt[i+1][j],opt[i][j+1]) return opt[n][n]

**Solution 2: * * according to the law of palindrome. Using the idea of dynamic programming

class Solution: def longestPalindromeSubseq(self, s: str) -> int: # Four elements of dynamic programming # Step 1: confirm the status # dp[i][j] indicates the longest palindrome sequence in the string composed of the ith character to the jth character of the s character; # Step 2: transfer equation # If the i-th character of S is the same as the j-th character, s[i]=s[j] # dp[i][j] = df[i+1][j-1] # If s [i]= s[j] # dp[i][j] = max(dp[i+1][j],dp[i][j-1]), select the longest one (regardless of when to delete it, because when the two sides are not equal, it is equivalent to filtering it out) # Step 3: initialization # dp[i][j] = 1, single character # Step 4: sequence # i traverses forward from the last character and j traverses backward from i + 1, which can ensure that each sub problem has been solved. n = len(s) dp = [[0]*n for _ in range(n)] for i in range(n-1,-1,-1): dp[i][i] = 1 for j in range(i+1,n): if s[i] == s[j]: dp[i][j] = dp[i+1][j-1]+2 else: dp[i][j] = max(dp[i+1][j],dp[i][j-1]) return dp[0][n-1]

## 2.4 the best time to buy and sell stocks

Given an array of prices, its ith element price [i] represents the price of a given stock on day I.

You can only choose to buy this stock one day and sell it on a different day in the future. Design an algorithm to calculate the maximum profit you can make.

Return the maximum profit you can make from this transaction. If you can't make any profit, return 0.

Example 1:

Input: [7,1,5,3,6,4]

Output: 5

Explanation: buy on day 2 (stock price = 1) and sell on day 5 (stock price = 6). Maximum profit = 6-1 = 5.

Note that the profit cannot be 7-1 = 6, because the selling price needs to be greater than the buying price; You can't buy shares before you sell them at the same time.

Example 2:

Input: prices = [1,4,7]

Output: 0

Explanation: in this case, no transaction is completed, so the maximum profit is 0.

Tips:

1 <= prices.length <= 105

0 <= prices[i] <= 104

**Solution: * * continuously update the minimum value of the previous i day according to the idea of dynamic programming, and get closer to the maximum income according to the price of the i day.

class Solution: def maxProfit(self, prices: List[int]) -> int: #dynamic programming #1. Confirmation status: the minimum value of the previous i day (the price on day i minus the minimum value of the previous i day is the maximum income on day i) #2. Confirm the state transition equation: the price of day i+1 minus the minimum value of the previous day i. Update minimum #3. Initial conditions: the maximum return is 0, and the minimum value on the first day is prices[0] #4. Sequence, traversing by time M = 0 opt = [prices[0] if prices else None] for i in prices[1:]: opt.append(min(opt[-1],i)) M = max(M,i-opt[-1]) return M

## 2.5 the best time to buy and sell stocks II

Give an array prices, where prices[i] represents the price of the stock on day I.

On each day, you may decide to buy and / or sell shares. You can only hold at most one share at any time. You can also buy it and sell it on the same day.

Return the maximum profit you can make.

Example 1:

Input: prices = [7,1,5,3,6,4]

Output: 7

Explanation: if you buy on the second day (stock price = 1) and sell on the third day (stock price = 5), this exchange can make a profit = 5-1 = 4.

Then, buy on the 4th day (stock price = 3) and sell on the 5th day (stock price = 6). This exchange can make a profit = 6-3 = 3.

Example 2:

Input: prices = [1,2,3,4,5]

Output: 4

Explanation: if you buy on the first day (stock price = 1) and sell on the fifth day (stock price = 5), this exchange can make a profit = 5-1 = 4.

Note that you can't buy stocks on day 1 and day 2 and then sell them. Because this is involved in multiple transactions at the same time, you must sell the previous shares before buying again.

Example 3:

Input: prices = [7,6,4,3,1]

Output: 0

Explanation: in this case, no transaction is completed, so the maximum profit is 0.

Tips:

1 <= prices.length <= 3 * 104

0 <= prices[i] <= 104

**Solution: * * use the idea of dynamic programming to calculate the essence.

class Solution: def maxProfit(self, prices: List[int]) -> int: #Try every day. Here's a problem. One day, sell yesterday and sell today. Although it doesn't meet the problem, the income is the same #1. Confirmation status, maximum income in the previous i days #2. Confirm the state transition equation, update the maximum return of i+1 day and update the minimum value #3. The initial state is determined, and the maximum value on day 0 is 0 #4. The sequence shall be determined according to the time opt = [0] for i in range(1,len(prices)): opt.append(max(opt[-1]+prices[i]-prices[i-1],opt[-1])) return opt[-1]