数据结构与算法:动态规划

动态规划

三大算法:分治法、动态规划与贪婪算法
分治法与动态规划的区别:
分治法将大问题分成小问题,例如二分法。子问题属性不变,小问题之间互相独立,需要做一个合并的过程(从上到下的方法)

动态规划也是将大问题拆解成小问题,不同之处是他的小问题有很多重复的,我们不需要重复的做,只需要将这些小问题存储起来,便于之后的查询,这种现象叫做记忆法!(从下到上的方法:先解决这些小问题)

斐波那契数列就是典型的动态规划

要做DP的问题需要给出一个公式,这个很重要

一维动态规划

1、给定n,找到不同的将n写成1,3,4相加的方法有多少个,顺序不一样算一种

n = 5,输出6
n = 1+1+1+1+1=1+3+4=1+3+1=3+1+1=1+4=4+1

解析:与斐波那契数一样,f(n) = f(n-1) + f(n-3) + f(n-4)
f(0) = f(1) = f(2) = 1 f(3) = 2 f(4) = 4

def count(n):
    dp = [None] * (n+1)
    dp[0] = dp[1] = dp[2] = 1
    dp[3] = 2
    for i in range(4,n+1):
        dp[i] = dp[i-1] + dp[i-3] + dp[i-4]
    return dp[5]

2、找到不相邻的加和最大数

假设你是一个职业抢劫犯,你打算洗劫一个街道,每一个房子中都有一定数量的钱,限制你的唯一条件是相邻的房子的安保系统是相连的,如果你抢劫相邻房子那么保安系统就会报警

给定一个非负整数的列表代表每个房子中的钱,计算在不惊动警察的情况下你可以抢劫到的最多的钱

在这里插入图片描述

def robe(array):
    n = len(array)
    # 生成两行n+1的0,第一列都为0,代表初始值
    # 规定第二行不取当前值所达到的最大值,第一行取当前值所达到的最大值
    dp = [[0 for _ in range(n + 1)] for _ in range(2)]
    for i in range(1,n + 1):
        dp[0][i] = dp[1][i-1] + array[i-1]
        dp[1][i] = max(dp[0][i-1], dp[1][i-1])
    return max(dp[0][n], dp[1][n])

array = [2,7,9,3,1]
robe(array)
> 12

这里是引入了两个空间,因此时间复杂度为N,空间复杂度也为N.但其实我们每次只用到了当前值的前面的那两个数字,因此我们可以做出优化,不用引入空间。

def robe(array):
    n = len(array)
    # 初始值
    yes, no = 0, 0
    for i in range(n):
#         no = max(yes, no) 不对,他们两个应该是同时变化
#         yes = no + array[i]
        yes, no = no + array[i], max(yes, no)
    return max(yes, no)

变形,现在这些银行排成一个圆环该如何做

如果是一个圆环的话,我们可以再上述的情况下,加一下思考:圆环我们肯定是要选择一个起点和终点的,只不过选择了起点就不能选择终点了,f(n)分成两种情况:1、选择起点,剩下的n-1,就和非变形的一样了,f(1, n-1); 2、不选择起点,那么可以选择第二个元素f(2, n-1)

def rob_round(array):
    def robe(array):
        n = len(array)
        # 初始值
        yes, no = 0, 0
        for i in range(n):
            yes, no = no + array[i], max(yes, no)
        return max(yes, no)
    return max(robe(array[:-1]), robe(array[1:]))
def rob(nums):
    if len(nums) == 0:
        return 0

    if len(nums) == 1:
        return nums[0]

    return max(robRange(nums, 0, len(nums) - 1),\
               robRange(nums, 1, len(nums)))

def robRange(nums, start, end):
    yes, no = nums[start], 0
    for i in range(start + 1, end): 
        no, yes = max(no, yes), i + no
    return max(no, yes)
发布了49 篇原创文章 · 获赞 2 · 访问量 1821

猜你喜欢

转载自blog.csdn.net/liuluTL/article/details/105435995