单序列动态规划

1 题型分析

  • 输入是单序列,求前i个元素的某种性质
    • state : f[i]表示前i个位置/数字/字符,第i个...
    • function : f[i] = f[j]... (j < i)
    • initialize : f[0] ...
    • answer : f[n] ..
  • 初始化dp[0]表示空序列
    • 坐标型dp[0]表示以$$a_i$$结尾的子序列性质

2 相邻约束型

256 Paint House

房子涂色,三种颜色,相邻的房子不能染成相同的颜色,求最小costs

  • 状态:设油漆i栋房子并且房子i-1是红色、蓝色、绿色的最小花费分别为 dp[i][0], dp[i][1], dp[i][2]
  • 初始化dp[0][0], dp[0][1], dp[0][2]
  • 答案是min{dp[N][0], dp[N][1], dp[N][2]}. 时间复杂度O(N), 空间复杂度O(N)

265 Paint House II

和I相同,但是房子可以涂k种颜色

  • dp[i][j] = min{dp[i-1][k]}(k!=j) + cost[i-1][j]
  • $$O(nk^2)$$ -> $$O(nk)$$, 每个元素的最小值?
  • 只需要知道该序列的最小值和次小值

198 House Robber

偷房子里的钱,但是相邻的房子不能同时偷,求最大能偷多少钱?

  • 确定状态:偷或者不偷最后一栋房子N-1
  • dp[i] = max(dp[i-1], dp[i-2]+nums[i])

213 House Robber II

和I一样,但是房子成了一个圈(房子0和房子n-1不能同时偷)

  • 分两个情况,不偷房子0和不偷房子n-1

3 最长序列系列

子数组和子序列(连续,不连续)

  • Sub-array: contiguous elements in an array,仅有$$n^2$$个
  • Sub-sequence: not necessarily contiguous,子序列有n!个
  • 输入序列,求符合条件的最长子序列

300 Longest Increasing Subsequence

最长升序子序列(可不连续)

解法1 DP O($$n^2$$)

  • dp[i]表示以a[i]结尾的最长上升子序列的长度
  • 用DP将时间复杂度从$$O(n!)$$ => $$O(n^2)$$

解法2 Ending + Binary Search O(nlogn)

  • ending数组代表的长度为i最小的结尾值
    • index 表示最长上升子序列的长度
    • value 表示该长度下的最小ending的值
    • ending 数组是单调递增的序列
class Solution(object):
    def lengthOfLIS(self, nums):
        if not nums: return 0
        n = len(nums)
        ends = [nums[0]]
        for i in xrange(1, n):
            if nums[i] > ends[-1]:
                ends.append(nums[i])
                continue
            # Binary Search >= target
            start, end = 0, len(ends)-1
            while start < end:
                mid = start + (end - start) // 2
                if ends[mid] < nums[i]:
                    start = mid + 1
                else:
                    end = mid
            ends[start] = nums[i]
        return len(ends)

354 Russian Doll Envelopes

解法2 DP O($$n^2$$) (TLE)

  • 排序后,就化简成了最长上升子序列的问题

4 矩阵型

221. Maximal Square

  • 求矩阵里,实心正方形个数?
    • How many Square? O($$n^3$$)
class Solution(object):
    def maximalSquare(self, matrix):
        if len(matrix) <= 0: return 0

        m, n = len(matrix), len(matrix[0])
        dp = [[0]*(n+1) for _ in xrange(m+1)]
        res = 0
        for i in xrange(m):
            for j in xrange(n):
                if matrix[i][j] == '1':
                    dp[i+1][j+1] = min(dp[i][j], dp[i+1][j], dp[i][j+1]) + 1
                    res = max(res, dp[i+1][j+1])
        return res * res

results matching ""

    No results matching ""