动态规划

1. 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

class Solution:
    #定义一个函数f(n),以第n个数为结束点的子数列的最大和,存在一个递推关系f(n) = max(f(n-1) + A[n], A[n]);
    def f(self,n,nums):
        if n==0:
            return nums[0]
        return max(self.f(n-1,nums)+nums[n],nums[n])
        
    #将这些最大和保存下来后,取最大的那个就是,最大子数组和。
    def maxSubArray(self, nums):
        nums_len=len(nums)
        result=float("-inf")
        for i in range(0,nums_len):#从0开始
            result=max(self.f(i,nums),result)
        return result

2. 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。
在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。
给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。

注意:本题相对原题稍作改动

 

示例 1:

输入: [1,2,3,1]
输出: 4
解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。

示例 2:

输入: [2,7,9,3,1]
输出: 12
解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。

示例 3:

输入: [2,1,4,5,3,1,1,3]
输出: 12
解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。

方法一:设计二维状态变量
第 1 步:设计状态

「状态」这个词可以理解为「记录了求解问题到了哪一个阶段」。

由于当前这一天有按摩师有两种选择:(1)接预约;(2)不接预约。但根据题意,今天是否接预约,是受到昨天影响的。为了消除这种影响,我们在状态数组要设置这个维度。

dp[i][0] 表示:区间 [0,i] 里不接受预约请求,并且下标为 i 的这一天不接受预约的最大时长;
dp[i][1] 表示:区间 [0,i] 里接受预约请求,并且下标为 i 的这一天接受预约的最大时长。

今天只和昨天的状态相关,依然是分类讨论:

今天不接受预约:或者是昨天不接受预约,或者是昨天接受了预约,取二者最大值,即:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]);
今天接受预约:只需要从昨天不接受预约转移而来,加上今天的时常,即:dp[i][1] = dp[i - 1][0] + nums[i]。

第 3 步:考虑初始化

从第 2 天开始,每天的状态值只与前一天有关,因此第 1 天就只好老老实实算了。好在不难判断:dp[0][0] = 0 与 dp[0][1] = nums[0];

class Solution:
       
    def massage(self, nums):
        nums_len = len(nums)
        if nums_len == 0:
            return 0
        if nums_len == 1:
            return nums[0]
        dp = [[0 for i in range(2)] for j in range(nums_len)]


        dp[0][0] = 0
        dp[0][1] = nums[0]
        
        for i in range(nums_len):
            # 今天不接受预约
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1])
            # 今天接受预约
            dp[i][1] = dp[i - 1][0] + nums[i]
        return max(dp[nums_len - 1][0], dp[nums_len - 1][1])

 3.求最长上升子序列个数

找出以元素i结尾的最长递增子序列

每一次为i进行分配时,要检查前面所有的算法ai(i<x)

若ai小于ax,则说明ax可以跟在ai后形成一个新的递增子序列

否则,以ax结尾的递增子序列的最长长度为1

# F[1] = 1;
# F[i] = max{1,F[j]+1|aj<ai && j<i}
def f(nums):
    if len(nums)<=1:
        return len(nums)
    #存放各个字串的最长上升序列个数
    men=[1 for i in range(len(nums))]
    for i in range(1,len(nums)):
        for j in range(0,i):
            if nums[j]<nums[i]:
                #跟新各个字串的最长上升序列个数
                men[i]=men[j]+1
    print(men)
    return max(men)
list01=[6,2,1,3,7]
print(f(list01))

 


posted on 2020-10-09 16:38  happygril3  阅读(129)  评论(0)    收藏  举报

导航