动态规划-爬楼梯

"""
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,
影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,
如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,
一夜之内能够偷窃到的最高金额。

"""

#递归
class Solution(object):
    def rob(self, nums):
        n=len(nums)
        def dfs(i):
            if i<0:
                return 0
            res=max(dfs(i-1),dfs(i-2)+nums[i])
            #不会越界,因为dfs是函数
            #dfs(0) 会调用 max(dfs(-1), dfs(-2) + nums[0])
            #此时 dfs(-1) 和 dfs(-2) 都会返回 0,因为 i < 0,表示已经超出索引范围
            return res
        return dfs(n-1)#从第i个得到的最大值开始,递归到前i-1个*思想*


#建立列表,还是递归啊
class Solution(object):
    def rob(self, nums):
        n=len(nums)
        cache=[-1]*n #设置一个全-1列表,用来记录dfs(i)
        def dfs(i): #i是要偷的房屋数目
            if i<0:
                return 0
            if cache[i]!=-1: #说明这个数已经被记录了
                return cache[i]
            cache[i]=max(dfs(i-1),dfs(i-2)+nums[i])
            return cache[i]
        return dfs(n-1)


#滑动窗口
class Solution(object):
    def rob(self, nums):
        n=len(nums)
        f0=f1=0 #f0是上上个,f1是上一个
        for i,x in enumerate(nums): #遍历每一间房子
            new_f=max(f1,f0+x)
            f0=f1 #一直在更新,没有存在列表中
            f1=new_f
        return f1

        #enumerate(nums) 会生成一个可迭代对象
        #返回的是每个元素的索引和值的元组
        #i 是索引,表示当前元素在 nums 列表中的位置
        #x 是值,表示当前索引位置对应的房子的金额



#动态规划
class Solution(object):
    def rob(self, nums):
        n=len(nums)
        dp=[0]*(n+2) #建立更新的列表
        for i,x in enumerate(nums):
            dp[i+2]=max(dp[i+1],dp[i]+x)
        return dp[-1]



"""
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
"""

#滑动窗口
class Solution(object):
    def climbStairs(self, n):#n是楼梯阶数
        f0=0
        f1=1
        for i in range(n):
            new_f=f0+f1
            f0=f1
            f1=new_f
        return f1


#递归和列表
class Solution(object):
    def climbStairs(self, n):#n是楼梯阶数
       cache=[-1]*(n+2)
       def dfs(i):
           if i<=1:#防止过界
               return 1
           if cache[i]!=-1:
               return cache[i]
           cache[i]=dfs(i-1)+dfs(i-2)
           return cache[i]
       return dfs(n)


#动态规划
class Solution(object):
    def climbStairs(self, n):#n是楼梯阶数
        f=[0]*(n+2)
        f[0]=f[1]=1
        for i in range(2,n+1):
            f[i]=f[i-1]+f[i-2]
            print(f)
        return f[n]


"""
给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。
一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。
"""

#动态规划
class Solution(object):
    def minCostClimbingStairs(self, cost):
        n=len(cost)
        m=[-1]*(n+1)
        m[0]=0
        m[1]=0
        for i in range(2,n+1):
            m[i]=min(m[i-1]+cost[i-1],m[i-2]+cost[i-2])
        return m[n]


#滑动窗口
#比动态规划要快,内存差不多
class Solution(object):
    def minCostClimbingStairs(self, cost):
        n=len(cost)
        f0=0 #上上一个
        f1=0 #上一个
        for i in range(2,n+1):
            new_f=min(f0+cost[i-2],f1+cost[i-1])
            f0=f1
            f1=new_f
        return f1




"""
给你一个由 不同 整数组成的数组 nums ,
和一个目标整数 target 。
请你从 nums 中找出并返回总和为 target 的元素组合的个数。
"""

#动态规划
class Solution(object):
    def combinationSum4(self, nums, target):
        dp=[0]*(target+1) #用来总和为target的元素组合的个数的列表
        dp[0]=1
        for i in range(1,target+1):
            for x in nums:
                if i>=x: #还没爬完,只用试一个具体值,剩下的是用几个具体值组成的
                    dp[i]=dp[i]+dp[i-x]
                    #一步爬x个台阶,上一个可能就是在i-x个台阶上,一直更新dp[i]
        return dp[target]


"""
给你整数 zero ,one ,low 和 high ,
我们从空字符串开始构造一个字符串,每一步执行下面操作中的一种:
将 '0' 在字符串末尾添加 zero  次。
将 '1' 在字符串末尾添加 one 次。
以上操作可以执行任意次。
如果通过以上过程得到一个 长度 在 low 和 high 之间(包含上下边界)的字符串,
那么这个字符串我们称为 好 字符串。
请你返回满足以上要求的 不同 好字符串数目。
由于答案可能很大,请将结果对 109 + 7 取余 后返回。
"""



class Solution(object):
    def countGoodStrings(self, low, high, zero, one):
        a=high-low
        res=0
        if high < zero and high < one:
            return 1
        dp=[0]*(high+1) #每一个元素对应着一个长度的所有组合的所有可能
        dp[0]=1 #长度为0有一种组合方式,就是空
        for i in range(1,high+1):
            dp[i]=dp[i-zero]+dp[i-one]
        for i in range(0,a+1):
            res=res+dp[low+i]
        res=res%(10**9+7)
        return res


from itertools import groupby
class Solution(object):
    def countTexts(self, pressedKeys):
       f=[1,1,2,4] #长度为索引值时的所有可能
       g=[1,1,2,4] #初始值,为了防止溢出
       for i in range(4,10**5+1): #长为i的相同字符的组合方式
           new_f=f[i-1]+f[i-2]+f[i-3]
           f.append(new_f%(10**9+7))
           new_g=g[i-1]+g[i-2]+g[i-3]+g[i-4]
           g.append(new_g%(10**9+7))

       ans = 1
       for ch, s in groupby(pressedKeys):
           m = len(list(s))
           if ch in '79':
               ans=ans*g[m]
           else:
               ans=ans*f[m]
       return ans%(10**9+7)


from itertools import groupby
nums = [1, 1, 2, 2, 2, 3, 3, 1]
grouped = groupby(nums)
for key, group in grouped:
    print(f"Key: {key} -> Group: {list(group)}")
#Key是数,group是数目
"""
groupby常用于对可迭代对象中的连续相同元素进行分组。
它将相同元素连续的部分分为一组,
返回一个生成器对象,可以方便地遍历每一组
"""


#动态规划
#建立dp表,用来储存第i个数量时的最优解
#给列表的前一个两个赋初值,给几个赋了初值,for循环就从他下一个开始
#for循环为了求dp表的值
#动态转移方程,列表递归

#滑动窗口
#几个变量 f0,f1赋初值
#for循环为了遍历到第i个数量时的最优解
#动态转移方程
#new_f=max(f1,f0+x)
#f0=f1
#f1=new_f

#有总长度,有定长想爬楼梯,第i个开始,定长x,它的前i-x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值