动态规划Ⅲ

一、0/1 背包

• 你背着一个背包闯入一家珠宝店,店里有林林总总的格式珠宝,各不重样。每一个珠
宝都有重量和价值。但是你的书包有承载上限。
• 想成为江湖老大,你需要找到一种装包方法使得包内物品的重量不超过其限定值且使
包内物品的价值最大
def knapSack(W, wt, val, n):
    K = [[0 for x in range(W+1)] for x in range(n+1)]
 
    # Build table K[][] in bottom up manner
    for i in range(n+1):
        for w in range(W+1):
            if i==0 or w==0:
                K[i][w] = 0
            elif wt[i-1] <= w:
                K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]],  K[i-1][w])
            else:
                K[i][w] = K[i-1][w]
 
    return K[n][W]

二、最长公共子串

Given two strings ‘X’ and ‘Y’, find the length of the longest common substring.

Input : X = "abcdxyz", y = "xyzabcd"

Output : 4

The longest common substring is "abcd" and is of length 4.

Input : X = "zxabcdezy", y = "yzabcdezx"

Output : 6

The longest common substring is "abcdez" and is of length 6.

def LCS(X, Y, m, n):
     
    matrix = [[0 for k in range(n+1)] for l in range(m+1)]
     
    result = 0
 
    for i in range(m + 1):
        for j in range(n + 1):
            if (i == 0 or j == 0):
                matrix[i][j] = 0
            elif (X[i-1] == Y[j-1]):
                matrix[i][j] = matrix[i-1][j-1] + 1
                result = max(result, matrix[i][j])
            else:
                matrix[i][j] = max(matrix[i-1][j], matrix[i][j-1])
    return result
三、最大递增子序列
给定一个长度为N的数组,找出一个最长的单调自增子序列(LIS)(不
一定连续,但是顺序不能乱)。
• 例如:给定一个数组 { 10, 22, 9, 33, 21, 50, 41, 60, 80 } ,则
其最长的单调递增子序列为{10,22,33,50,60,80},长度为6.
 
方法一:借助上一题lcs
def lengthOfLIS1(nums):
    sortNums = sorted(nums)
    n = len(nums)
    return LCS(nums, sortNums, n, n)

方法二:动态规划 O(N**2)

def lengthOfLIS2(nums):
    if not nums:
        return 0
    dp = [1]*len(nums)
    for i in range (1, len(nums)):
        for j in range(i):
            if nums[i] >nums[j]:
                dp[i] = max(dp[i], dp[j]+1)
    return max(dp)

方法三:二分  O(nlogn)

#using binary search
def lengthOfLIS(nums):
    def search(temp, left, right, target):
        if left == right:
            return left
        mid = left+(right-left)//2
        return search(temp, mid+1, right, target) if temp[mid]<target else search(temp, left, mid, target)
    temp = []
    for num in nums:
        pos = search(temp, 0, len(temp), num)
        if pos >=len(temp):
            temp.append(num)
        else:
            temp[pos]=num
    return len(temp)

另:

#using binary search
def lengthOfLIS(nums):

    temp = []
    for num in nums:
        pos = bisect(temp, num) 
        if pos >=len(temp):
            temp.append(num)
        else:
            temp[pos]=num
    return len(temp)

注意:temp数组中存储的不是递增子序列,但长度和所要的答案数组长度相同。

 

 
posted @ 2020-05-07 12:21  oldby  阅读(146)  评论(0编辑  收藏  举报