坐标型动态规划
1 题型分析
- 动态规划里较简单一类(以...结尾来分析)
- Input是序列或者网格(一维Array,字符串,二维Matrix)
- Output是需要找到序列中某个/些子序列或网格中的某条路径
- 某种性质最大/最小
- 计数
- 存在性
- 动态规划方程dp[i]中的下标i表示以$$a_i$$为结尾的满足条件的子序列的性质;dp[i][j]中的下标表示以格子(i,j)为结尾的满足条件的路径的性质
- 初始条件dp[0]就是指以$$a_0$$为结尾的子序列的性质
2 序列(Array, String)
序列型dp的状态以i-th为结尾来分析
45. Jump Game II
给一个Array,求从第一个index跳到最后一个index需要的最少步数?
解法1 DP O($$n^2$$)TLE (98/99 pass)
- dp[i]表示到达当前点需要的最少步数
- 从后向前遍历, $$O(n^2)$$
- dp[i] = 1 + min(dp[j]) j > i and j can be reached from i by only one jump
解法2 Greedy O(n)
class Solution(object): # 有点难理解
def jump(self, nums):
last = cur = res = 0
for i in xrange(len(nums)): # last 表示最后一步所在位置
if i > last:
last = cur
res += 1
cur = max(cur, i+nums[i]) # cur 表示当前能达到的最大位置
return res
53. Maximum Subarray
给一个Array,求和最大的subarray
- 状态:以i-th个元素为ending的subarray的最大值
- Why?只有以最后一个元素结尾,我们才能把结果往后传递,得出递推公式
class Solution(object): def maxSubArray(self, nums): if not nums: return 0 cur = res = nums[0] for i in xrange(1, len(nums)): cur = max(nums[i], cur+nums[i]) res = max(res, cur) return res
Follow up
- (1) 空间优化 what if we want to optimize the space complexity?
- (2) 返回具体结果 what if we want you to return the start and end indices of the solution array?
- when to move the start and end?
- need sol_start, sol_end
472. Concatenated Words
给一个词典,判断一个字符串是不是由词典中的单词拼接而成
674. Longest Continuous Increasing Subsequence
Given an unsorted array of integers, find the length of longest continuous increasing subsequence (subarray). 连续子序列Subarray总共也就$$O(n^2)$$个,通过动态规划时间复杂度降为$$O(n)$$,以第i个元素结尾的最长连续子序列可以把递推公式dp[i]和dp[i-1]串起来!
- State:dp[i]表示 from the 0-th element to the i-th element, the value of the longest ascending subarray, (including the i-th element)
- Init:dp[0] = 1
- Function:dp[i] = dp[i-1] + 1(if nums[i] > nums[i-1]) else 1
- Answer:dp[n]
3 矩阵(网格)
62 Unique Paths
计数:求总路径数
- **State**: dp[x][y]表示起点到[x,y]路径数
- **Function**: dp[x][y] = dp[x-1][y] + dp[x][y-1]
- **Init**: dp[0][j] = 1, dp[i][0] = 1
63 Unique Paths II
- 计数:求总路径数,但是有障碍物
64 Minimum Path Sum
- 最小值:求路径当中最短的路径
361 Bomb Enemy
网格中有wall-'W',enemy-'E'和empty-'0',空的地方可以放炸弹,问一个炸弹最多可以炸死多少敌人?有点像游戏“泡泡堂”里的炸弹。
- 四个方向up,down,left,right
4 空间优化
滚动数组
- dp[i] = dp[i-1] + 1
- dp[x][y] = dp[x-1][y] + dp[x][y-1]
- 这种只和前一个或者前一行元素有关的递推公式,可以用滚动数组来做空间优化!
- 根据行列的大小可以选择更小的来进行滚动,这样更节省空间