Leetcode 动态规划の简单题集合训练(198 303 746 1025) python

198.打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

示例 1:

输入: [1,2,3,1] 输出: 4 解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。 示例 2:

输入: [2,7,9,3,1] 输出: 12 解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5
号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。

方程写出来非常的简单,基本思想就是维护输出结果的数组永远记录第i间房屋能偷盗的最大值,比较的时候只用比较当前的偷盗值和前一间房屋的偷盗值,取个最大值就ok
res[i] = res[i-2] + nums[i]

class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums: return 0
        if len(nums) == 1: return nums[0]
        if len(nums) == 2: return max(nums)
        res = [None]*(len(nums))
        res[0] = nums[0]
        res[1] = max(nums[0], nums[1])
        for i in range(2, len(nums)):
            res[i] = max(res[i-2] + nums[i], res[i-1])
        return res[-1]   

303. 区域和检索 - 数组不可变

给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。

示例:

给定 nums = [-2, 0, 3, -5, 2, -1],求和函数为 sumRange()

sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRange(0, 5) -> -3 说明:

你可以假设数组不可变。 会多次调用 sumRange 方法。

直接用python中的切片操作,但是耗时非常之久,于是我看了一下前5%的解答,还真的要用动规emmm
在这里插入图片描述

class NumArray(object):

    def __init__(self, nums):
        """
        :type nums: List[int]
        """
        self.nums = nums

    def sumRange(self, i, j):
        """
        :type i: int
        :type j: int
        :rtype: int
        """
        return sum(self.nums[i:j+1])
        


# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(i,j)
动态规划
class NumArray(object):

    def __init__(self, nums):
        """
        :type nums: List[int]
        """
        if nums:
            self.sum = [nums[0]]
            for i in range(1, len(nums)):
                self.sum.append(self.sum[i-1] + nums[i])

    def sumRange(self, i, j):
        """
        :type i: int
        :type j: int
        :rtype: int
        """
        return self.sum[j] - (self.sum[i-1] if i >= 1 else 0)

746. 使用最小花费爬楼梯

数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i] (索引从0开始)。

每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。

您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。

示例 1:

输入: cost = [10, 15, 20] 输出: 15 解释: 最低花费是从cost[1]开始,然后走两步即可到阶梯顶,一共花费15。
示例 2:

输入: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 输出: 6 解释:
最低花费方式是从cost[0]开始,逐个经过那些1,跳过cost[3],一共花费6。 注意:

cost 的长度将会在 [2, 1000]。 每一个 cost[i] 将会是一个Integer类型,范围为 [0, 999]。

重点就是没到楼顶之前的每一层的res[i]一定要加上自身的cost[i],而对于楼顶的一层是可以不用加cost[-1]的值的,就这一个差别

class Solution(object):
    def minCostClimbingStairs(self, cost):
        """
        :type cost: List[int]
        :rtype: int
        """
        if not cost: return 0 #先讨论一下极限情况
        if len(cost) == 1: return cost[0]
        if len(cost) == 2: return min(cost)
        res = cost
        for i in range(2, len(cost)-1):
            res[i] += min(res[i-2], res[i-1])
        return min(res[len(cost)-2], res[len(cost)-3] + res[len(cost)-1])
        # return min(res[len(cost)-2], res[len(cost)-3] + cost[-1])#也是一样的

1025. 除数博弈

爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。

最初,黑板上有一个数字 N 。在每个玩家的回合,玩家需要执行以下操作:

选出任一 x,满足 0 < x < N 且 N % x == 0 。 用 N - x 替换黑板上的数字 N 。
如果玩家无法执行这些操作,就会输掉游戏。

只有在爱丽丝在游戏中取得胜利时才返回 True,否则返回 false。假设两个玩家都以最佳状态参与游戏。

示例 1:

输入:2 输出:true 解释:爱丽丝选择 1,鲍勃无法进行操作。 示例 2:

输入:3 输出:false 解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。

提示:

1 <= N <= 1000

其实我也讲不清楚这里面的逻辑,因为写出来送去判题的时候又觉得写的怪怪的可能写错,可是还是通过了
大致的说一下:
其实题目的意思就是问这样操作能否得出偶数步的解(如果第一步的index是1的话就是奇数步解)
维护一个列表d,记录每个小于x的值去除N的情况下会走的步数,然后加上x值走的步数就ok

class Solution(object):
    def divisorGame(self, N):
        """
        :type N: int
        :rtype: bool
        """
        if N == 1: return False
        step = 0
        d = [0]
        for x in range(1, N):
            step += d[-1] #取上一步的结果
            while N % x == 0 and N-x > 0:
                N = N - x
                step += 1
            d.append(step)
            if step % 2 == 1: return True %如果得到奇数步解就直接输出
        return False

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值