Dynamic Programming Flashcards

1
Q
  1. 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”

A
創一個nxn的DP matrix,DP[i][j]代表i~j是否是回文,
P(i,j)=(P(i+1,j−1) and Si ==Sj) 
DP[i][j] 是否回文 根據DP[i+1][j-1] 且Si ==Sj,所以可以如此DP下去。
先把dp[i][i] 都設定好
dp[i][i+1]也設定好
最後就是for loop去填其他dp
for loop 有一點trick
for j in xrange(len(s)):
            for i in xrange(j - 1):

loop 的走法可以是一個col一個col往右走(這個比較好寫)
也可以是走斜的格子(換句話說就是substring固定長度)
目的就是要先把Dp[i+1][j-1]做完

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q
  1. Regular Expression Matching
    Given an input string (s) and a pattern (p), implement regular expression matching with support for ‘.’ and ‘*’.

’.’ Matches any single character.
‘*’ Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).

Note:

s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like . or *.
Example 1:

Input:
s = "aa"
p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input:
s = "aa"
p = "a*"
Output: true
Explanation: '*' means zero or more of the preceding element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:
Input:
s = "ab"
p = ".*"
Output: true
Explanation: ".*" means "zero or more (*) of any character (.)".
Example 4:
Input:
s = "aab"
p = "c*a*b"
Output: true
Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore, it matches "aab".
Example 5:

Input:
s = “mississippi”
p = “misisp*.”
Output: false

A

It can use backtracking or DP.

Backtracking:
compare first letter every recursive.
分為兩種可能來return
if len(p) >= 2 and p[1] == ‘*’:

else

DP:
# dp initial
dp = [[False for _ in xrange(len(p) + 1)] for _ in xrange(len(s) + 1)]
dp[0][0] = True

    for j in xrange(1, len(dp[0])):
        if p[j-1] == '*':
            dp[0][j] = dp[0][j-2] # Define Transfer function for i in xrange(1, len(s) + 1):
        for j in xrange(1, len(p) + 1):
            if s[i - 1] == p[j - 1] or p[j - 1] == '.':
                dp[i][j] = dp[i - 1][j - 1]
            elif p[j - 1] == '*':
                if s[i-1] == p[j-2] or p[j-2] == '.':   # star means repeat preceding element
                    dp[i][j] = dp[i][j-2] or dp[i-1][j] # 就算星號前字母和s的相同,a*也可能代表重複0次,所以還是要考慮dp[i][j-2]
                else:                                   # star means zero
                    dp[i][j] = dp[i][j-2]
            else:
                dp[i][j] = False
    0  a  a  b
0  o  x  x  x
c  x   x  x  x
*   o  x  x  x 
a  x   o  x  x
*   o  o  o  x
b  x  x  x   o
if p[i-1] == s[j-1] or p[I-1] == '.' : 
    dp[i][j] = dp[i-1][j-1]
else:
    if p[I-1] == '*':
        if p[I-2] == s[j-1] or p[I-2] == '.':
            dp[i][j] = dp[i-1][j] or dp[i-2][j]
        else:
            dp[i][j] = dp[i-2][j]
    else:
        dp[i][j] = False
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q
  1. Longest Valid Parentheses
    Given a string containing just the characters ‘(‘ and ‘)’, find the length of the longest valid (well-formed) parentheses substring.
Example 1:

Input: “(()”
Output: 2
Explanation: The longest valid parentheses substring is “()”
~~~
Example 2:
~~~
Input: “)()())”
Output: 4
Explanation: The longest valid parentheses substring is “()()”
~~~
~~~

A
  1. DP
    Use DP. Initial a DP array, represent the longest valid parentheres end at i.
    the transistion function.
    Transition function:

dp[i] = dp[i-2] + 2 if “…..()”
2 + dp[i-1] + dp[i - dp[i-1] - 2] if “…..))” if i - dp[i-1] - 1 - 1 >= 0 and s[i - dp[i-1] - 1 - 1] == ‘(‘:

Only tow kind of situation the dp has value.
end with ‘()’, ‘))’. If end wirt ‘(‘, always invalid.
And the transistion function can be done depend on this two condition.
2. Stack
Using a stack to parse the parentheses is a very nature way to figure out when ‘)’ is coming, is there are enough ‘(‘. And you push the index into stack. So that you can calculate the length.
3. without extra space
parse from left. Only when left and right are equal. This is a valid subsequence.
And then parse from right. return the max
((()()(((

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q
  1. Edit Distance
    Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.

You have the following 3 operations permitted on a word:

Insert a character
Delete a character
Replace a character
Example 1:

Input: word1 = "horse", word2 = "ros"
Output: 3
Explanation: 
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')
Example 2:

Input: word1 = “intention”, word2 = “execution”
Output: 5
Explanation:
intention -> inention (remove ‘t’)
inention -> enention (replace ‘i’ with ‘e’)
enention -> exention (replace ‘n’ with ‘x’)
exention -> exection (replace ‘n’ with ‘c’)
exection -> execution (insert ‘u’)

A
  1. DP
    * 思路
    Define dp[i][j] as the edit distance between word1[:i] and word2[:j].
    Transition function:
    if last letter is the same
    d[i][j] = d[i-1][j-1]
    else
    dp[i][j] = 1 + (dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) (insert, delete, replace: means the edit distance of after doing these move)
        h o r s e
    0 1 2 3 4 5
r   1  1  2 2 3 4
o  2
s  3

D(“abbc”, “acc”)
=D(“abb”, “ac”). # no edit on last c
= 1 + min(D(“ab”, “ac” ), #delete ab[b] 如果我知道D(“ab”, “ac” )那我就先delete在edit
D(“abb”, “a”), #insert a[c]如果我知道D(“abb”, “a”) 就先edit在insert
D(“ab”, “a”)). # replace. ab[b] to a[c] 如果我知道D(“ab”, “a”)就replace b to c在edit

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q
  1. 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?

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

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

Constraints:

1 <= m, n <= 100
It’s guaranteed that the answer will be less than or equal to 2 * 10 ^ 9.

A

Use 2d dp array or 1d is fine.
dp = [0 for _ in xrange(m+1)]
dp size need to be m+1, n+1. Because for the first element need a dp[I-1] to get the do[I]. So we need initial the dp 1 longer and initialize the first row, col.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q
  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?

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
A

Use 2d dp array or 1d is fine.
dp = [0 for _ in xrange(m+1)]
dp size need to be m+1, n+1. Because for the first element need a dp[I-1] to get the do[I]. So we need initial the dp 1 longer and initialize the first row, col.
if there is a obstacle just let the dp[I][j] = 0

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q
  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.
A

dp[n+1][m+1]

dp = [float(‘inf’) for _ in xrange(len(grid[0]) + 1)]
initialize as float(‘inf’) because the min

Transition function
dp[j] = min(dp[j], dp[j-1]) + grid[i-1][j-1]

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q
  1. Decode Ways
    A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given a non-empty string containing only digits, determine the total number of ways to decode it.

Example 1:

Input: “12”
Output: 2
Explanation: It could be decoded as “AB” (1 2) or “L” (12).
Example 2:

Input: “226”
Output: 3
Explanation: It could be decoded as “BZ” (2 26), “VF” (22 6), or “BBF” (2 2 6).

A
Use 1D DP array.
transition function
if not s or s[0] == '0':    return 0
        dp = [0 for _ in xrange(len(s) + 1)]
        dp[0] = 1
        dp[1] = 1
        for i in xrange(2, len(dp)):
            if s[i-1] != '0':
                dp[i] += dp[i-1]
            if s[i-2] == '1' or s[i-2] == '2' and 0 <= int(s[i-1]) <= 6:    dp[i] += dp[i-2]
        return dp[-1]
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q
  1. Unique Binary Search Trees
    Given n, how many structurally unique BST’s (binary search trees) that store values 1 … n?

Example:

Input: 3
Output: 5
Explanation:
Given n = 3, there are a total of 5 unique BST’s:

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

Constraints:

1 <= n <= 19

A

1D DP array

choose a number as root.
Then you can divide all number into two groups.
Get each group possible unique tree from dp.
Then multiply the number of left and right subtree. This the answer

class Solution(object):
    def numTrees(self, n):
        """
        :type n: int
        :rtype: int
        """
        dp = [0 for _ in xrange(n+1)]
        # Transition Function
        # 1: 1
        # 2: 2
        # 3:
        dp[0] = 1
        dp[1] = 1
        for i in xrange(2, len(dp)):
            for j in xrange(1, i+1):
                dp[i] += dp[j-1] * dp[i-j]
        return dp[-1]
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q
  1. Unique Binary Search Trees II
    Given an integer n, generate all structurally unique BST’s (binary search trees) that store values 1 … n.

Example:

Input: 3
Output:
[
  [1,null,3,2],
  [3,2,null,1],
  [3,1,null,null,2],
  [2,1,3],
  [1,null,2,null,3]
]
Explanation:
The above output corresponds to the 5 unique BST's shown below:
   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

Constraints:

0 <= n <= 8

A
  1. if the output need to list all kind of possible combination. It must use recursive. You can also add a memo dictionary to implement DP recursive.
  2. First idea come out my mind is use a backtracking to iterative 1~n, Add a node in each recursive function. And delete the node after return the function. But this method can’t works for this problem. Because if you delete the node after return the function. The node in the result also are deleted. That will make the results are all None.
    Backtracking build up the combination when enter next recursive.
    But this problem, we need to let the recursive build sub combination and gather all sub combination when exist the recursive. And this idea is Divide and Conquer.
  3. How to implement Divide and Conquer.
    1,2,3,4,5
    for loop choose a node as the root of the sub-tree for example 3. Then 1,2 are the left tree of 3. 4,5 are the right tree of 3. let node = TreeNode(3)
    And call left = dfs(1,2), right = dfs(4,5). left and right a list of many combination. for loop all left and right combination and build all combination of tree rooted as 3.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q
  1. Triangle
    Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.

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 (i.e., 2 + 3 + 5 + 1 = 11).

Note:

Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

A

Use 2d array is easier.
Use dp = [[0 for _ in xrange(len(triangle[-1])+1)] for _ in xrange(len(triangle)+1)] is more complicate
you can use
dp = [[0 for _ in xrange(len(triangle[-1]))] for _ in xrange(len(triangle))]
Transition function: dp[i][j] = triangle[i][j] + min(dp[i-1][j-1], dp[i-1][j])
if it is the first element in the row, left = float(‘inf’). if it is the last element in the row, right = float(‘inf’)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q
  1. Word Break
    Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

Note:

The same word in the dictionary may be reused multiple times in the segmentation.
You may assume the dictionary does not contain duplicate words.
Example 1:

Input: s = “leetcode”, wordDict = [“leet”, “code”]
Output: true
Explanation: Return true because “leetcode” can be segmented as “leet code”.
Example 2:

Input: s = “applepenapple”, wordDict = [“apple”, “pen”]
Output: true
Explanation: Return true because “applepenapple” can be segmented as “apple pen apple”.
Note that you are allowed to reuse a dictionary word.
Example 3:

Input: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
Output: false

A

It is a kind of jump game. the jump step is depend on the word in dictionary words.

Initial a 1d dp array.
two for loop.
first, loop all letter in s.
Then from the I letter loop back to front. And check is there a substring in wordDict.

build a set
wordset = set()
for w in wordDict:
wordset.add(w)

        dp = [0] * (len(s) + 1)
        dp[0] = 1
        # dp[i] = dp[i-1] s[i:i+1] in wordset + dp[i-2] + ...
        for i in xrange(1, len(s) + 1):
            for j in xrange(i):
                if s[j:i] in wordset:
                    dp[i] += dp[j]
        return dp[-1] > 0
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q
  1. Word Break II
    Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences.

Note:

The same word in the dictionary may be reused multiple times in the segmentation.
You may assume the dictionary does not contain duplicate words.
Example 1:

Input:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
Output:
[
  "cats and dog",
  "cat sand dog"
]
Example 2:
Input:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
Output:
[
  "pine apple pen apple",
  "pineapple pen apple",
  "pine applepen apple"
]
Explanation: Note that you are allowed to reuse a dictionary word.
Example 3:
Input:
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
Output:
[]
A

Use recursive to solve this problem. Also use memo to memorize the sub problem ans.

Every recursive
loop the string and divide the string into left and right.
check if left in wordDict. If True dfs(right) and append answer.

Time Complexisty O(2^n)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q
  1. Maximum Product Subarray
    Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.

Example 1:

Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.
Example 2:

Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.

A

This problem need two dp
one for max product dp_max. one for min product dp_min
思路其實是dp_max去紀錄nums[any previous~i]的最大值,dp_min去紀錄nums[any previous ~i]的最小值
dp[i]會一直把i以前最大的值留下來,所以下一次只需要讓nums[i-1]和dp[i-1]去乘就可以,不用在考慮前面。
Transition function is:
dp_max[i] = max(nums[i-1], dp_max[i-1] * nums[i-1], dp_min[i-1 * nums[i-1]])

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q
  1. Maximal Square
    Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing only 1’s and return its area.

Example:

Input:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

Output: 4

A

Transition function is dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1.

There is one trick to speed up. if the res is >n. If the rest of the row is smaller than n. There is no need to check them.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q
  1. Ugly Number II
    Write a program to find the n-th ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5.

Example:

Input: n = 10
Output: 12
Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.
Note:

1 is typically treated as an ugly number.
n does not exceed 1690.

A

The naive solution is check is_ugly() for 1~n number.
But actually generate the ugly number directly is easy.
The ugly number can simply generated by previous ugly * (2,3,5), and we just need to append them by order.

The method is maintain three number nxt2, nxt3, nxt5 and index idx2, idx3, idx5.

min(nxt2, nxt3, nxt5) is the next ugly.
update the nxt2 by idx2 += 1 nxt2 = ugly_list[idx2] * 2

note: please use if not elif

17
Q
  1. Maximal Rectangle
    Given a 2D binary matrix filled with 0’s and 1’s, find the largest rectangle containing only 1’s and return its area.

Example:

Input:
[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
Output: 6
A

一行一行的累積建構一個histogram,然後用84題的思路做m遍

if matrix[I][j] == ‘1’:hist[j] += 1
else: hist[j] = 0

18
Q
  1. Scramble String
    We can scramble a string s to get a string t using the following algorithm:

If the length of the string is 1, stop.
If the length of the string is > 1, do the following:
Split the string into two non-empty substrings at a random index, i.e., if the string is s, divide it to x and y where s = x + y.
Randomly decide to swap the two substrings or to keep them in the same order. i.e., after this step, s may become s = x + y or s = y + x.
Apply step 1 recursively on each of the two substrings x and y.
Given two strings s1 and s2 of the same length, return true if s2 is a scrambled string of s1, otherwise, return false.

Example 1:

Input: s1 = “great”, s2 = “rgeat”
Output: true
Explanation: One possible scenario applied on s1 is:
“great” –> “gr/eat” // divide at random index.
“gr/eat” –> “gr/eat” // random decision is not to swap the two substrings and keep them in order.
“gr/eat” –> “g/r / e/at” // apply the same algorithm recursively on both substrings. divide at ranom index each of them.
“g/r / e/at” –> “r/g / e/at” // random decision was to swap the first substring and to keep the second substring in the same order.
“r/g / e/at” –> “r/g / e/ a/t” // again apply the algorithm recursively, divide “at” to “a/t”.
“r/g / e/ a/t” –> “r/g / e/ a/t” // random decision is to keep both substrings in the same order.
The algorithm stops now and the result string is “rgeat” which is s2.
As there is one possible scenario that led s1 to be scrambled to s2, we return true.
Example 2:

Input: s1 = “abcde”, s2 = “caebd”
Output: false
Example 3:

Input: s1 = “a”, s2 = “a”
Output: true

Constraints:

s1.length == s2.length
1 <= s1.length <= 30
s1 and s2 consist of lower-case English letters.

A

recursive 便利所有可能,加入memo來記憶做過的結果,用Counter數裡面letter的數量,如果不相同,就一定是false來達到剪枝。
recursive不斷的輸入s1, s2,在所有位置加斷點,並且遍歷使否對調。只要遇到s1, s2相同就是正確的。

19
Q
  1. Interleaving String
    Given s1, s2, and s3, find whether s3 is formed by the interleaving of s1 and s2.

Example 1:

Input: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac”
Output: true
Example 2:

Input: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbbaccc”
Output: false
Example 3:

Input: s1 = “”, s2 = “”, s3 = “”
Output: true

Constraints:

0 <= s1.length, s2.length <= 100
0 <= s3.length <= 200
s1, s2, and s3 consist of lower-case English letters.

A

標準的走迷宮遊戲,只是你要可以想到這題跟那個題型的關聯。

s3就是一個迷宮,每次你可以選擇用s1(go right) or s2 (go down),然後看是否可以走到最後都是True。

20
Q
  1. Distinct Subsequences
    Given a string S and a string T, count the number of distinct subsequences of S which equals T.

A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, “ACE” is a subsequence of “ABCDE” while “AEC” is not).

It’s guaranteed the answer fits on a 32-bit signed integer.

Example 1:

Input: S = “rabbbit”, T = “rabbit”
Output: 3
Explanation:
As shown below, there are 3 ways you can generate “rabbit” from S.
(The caret symbol ^ means the chosen letters)

rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^
Example 2:

Input: S = “babgbag”, T = “bag”
Output: 5
Explanation:
As shown below, there are 5 ways you can generate “bag” from S.
(The caret symbol ^ means the chosen letters)

babgbag
^^ ^
babgbag
^^    ^
babgbag
^    ^^
babgbag
  ^  ^^
babgbag
    ^^^
A

dp[i][j] = num of subseq of s[1:j] equals t[1:i]
when i==0. which means t=’’. no mater what s is. All s has 1 the same subseq. init it.

Transisition function
if t[i-1] == s[j-1]:
dp[i][j] = dp[i][j-1] + dp[i-1][j-1]
# if t[i-1] == s[j-1]. Then num of dp[i-1][j-1] can propodate.
else:
dp[i][j] = dp[i][j-1] # if dp[i][j-1] has num = x. dp[i][j] must also have num = x

21
Q
  1. Best Time to Buy and Sell Stock III
    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 at most two transactions.

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: prices = [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.
Example 2:

Input: prices = [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: prices = [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
Example 4:

Input: prices = [1]
Output: 0

Constraints:

1 <= prices.length <= 105
0 <= prices[i] <= 105

A

把array分為兩個array,然後分別用Best Time to Buy and Sell Stock I的解法去解,相加的profit是答案,然後遍歷所有分割的可能,取得最大的一個profit

for loop 得到一個array代表從0~i,的最大profit.
for loop 得到一個array代表從i~-1,的最大profit.
之後這兩個array相加就得到所有0~i + i~-1的profit,取得最大的就是答案

22
Q
  1. Palindrome Partitioning II
    Given a string s, partition s such that every substring of the partition is a palindrome.

Return the minimum cuts needed for a palindrome partitioning of s.

Example 1:

Input: s = “aab”
Output: 1
Explanation: The palindrome partitioning [“aa”,”b”] could be produced using 1 cut.
Example 2:

Input: s = “a”
Output: 0
Example 3:

Input: s = “ab”
Output: 1

Constraints:

1 <= s.length <= 2000
s consists of lower-case English letters only.

A
先用dp的方法算出valid[I][j] 所有位置是否是回文。
再用DP partition的模板去算
for loop計算dp[i] 0~i的min cut
    if valid[0][i]:
                dp[i] = 0
    for j in xrange(i):    #把0~I 試著partition I次 找出min cut
                if valid[j+1][i]:
                    dp[i] = min(dp[i], dp[j] + 1)