代码随想录 Day 33 | 【第八章 贪心算法 part 02】122.买卖股票的最佳时机II、55. 跳跃游戏、45.跳跃游戏II、1005.K次取反后最大化的数组和

一、122.买卖股票的最佳时机II

本题解法很巧妙, 本题大家可以先自己思考一下然后再看题解,会有惊喜!

1. 解题思路

        用当天减去前一天的价格就得到当天的利润,计算出每天的利润后,选取利润为正数的天数作为买卖股票的最佳时机,然后将这几天的利润相加得到最大利润。

2. 代码实现

(1)定义result变量将每天的利润累加在一起,初始化为0;

(2)遍历price数组,从下标为1开始,因为需要有前一天才可以计算利润。如果利润是负数的话,result不加,如果利润是正数,result加上当天利润。

(3)最后返回result。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        result = 0
        for i in range(1, len(prices)):
            benefit = prices[i]-prices[i-1]
            if benefit > 0:
                result += benefit
        return result

二、55. 跳跃游戏

本题如果没接触过,很难想到,所以不要自己憋时间太久,读题思考一会,没思路立刻看题解

1. 解题思路

        无需去思考到底跳几步,而只需要看最大覆盖范围是否可以将数组完全覆盖,如果可以则返回True,反之False。

2. 代码实现

(1)定义变量cover为覆盖的下标,初始化为0;

(2)如果数组的长度等于1,说明只有一个元素,那么一定可以覆盖,因为起始位置在终止位置;

(3)for循环遍历,i 只能在覆盖范围内移动,所以 i 一定小于等于cover:将cover更新为 i 加上nums[i],也就是遍历当前范围内的元素,并让所遍历的元素位置 i 加上其最大移动步数,就可以更新最大覆盖范围。如果cover等于数组的最后一位,那么说明可以覆盖整个数组,返回True。

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        cover = 0
        if len(nums) == 1:
            return True
        for i in range(len(nums)):
            if i <= cover:
                cover = max(i+nums[i], cover)
                if cover >= len(nums)-1:
                    return True
        return False

三、45.跳跃游戏II

本题同样不容易想出来。贪心就是这样,有的时候 会感觉简单到离谱,有时候,难的不行,主要是不容易想到。

1. 解题思路

用最少的步数尽可能增加覆盖范围,一旦覆盖范围覆盖至终点,就将步数进行输出。

2. 代码实现

(1)当传入的数组长度等于1时,当前起点就是终点,无需挪动,所以挪动0步,直接返回0。

(2)定义cur变量记录当前覆盖范围,初始化为0。当当前覆盖范围还没到终点时,需要启动下一步的覆盖范围,所以定义next变量记录下一步的覆盖范围,初始化为0。定义变量result用于记录具体跳几步。

(3)for循环遍历数组:由于只需要下一步记录最远的覆盖距离,所以next只更新最远的覆盖距离,用 i 加上nums[ i ]。

        如果 i 走到了当前覆盖范围的最大位置,也就是cur:

        1)判断如果当前位置不是终点,那么result需要再向前一步进入下一个覆盖范围,并且将next赋给cur。如果当前覆盖距离覆盖到终点,那么break,当前result就是结果。

        2)如果当前位置是终点,直接break。

class Solution:
    def jump(self, nums: List[int]) -> int:
        if len(nums) == 1:
            return 0
        result = 0
        cur = 0
        next = 0
        for i in range(len(nums)):
            next = max(i + nums[i], next)
            if i == cur:
                result += 1
                cur = next
                if cur >= len(nums)-1:
                    break
        return result

四、1005.K次取反后最大化的数组和

本题简单一些,估计大家不用想着贪心 ,用自己直觉也会有思路。

1. 解题思路

本题蕴含了两个贪心:1)排序后的数组中,优先对最大的负数进行取反,可以使数组和最大化;2)如果数组全为正数,而k未使用完,那么在排序后对最小的正数进行取反。

2. 代码实现

(1)首先对数组进行按照绝对值从大到小排序。

(2)for循环遍历数组:如果遍历的元素小于0且k>0,那么对其乘以(-1),并且k减1。此时在k充足的情况下,数组中元素全为正数。

(3)第二次贪心:k可能还没消耗,当剩下的k是奇数的时候,直接对末尾元素乘以1;如果k是偶数,则末尾元素正负保持不变。

在Python中,A.sort(key=lambda x: abs(x), reverse=True) 这行代码的作用是对列表 A 进行排序。排序的依据是列表中每个元素的绝对值,并且是按照从大到小的顺序进行排序(因为 reverse=True)。

这里有几个关键点需要解释:

  1. A.sort():这是列表(List)的一个方法,用于就地(in-place)对列表进行排序,即直接修改原列表而不是返回一个新的排序后的列表。

  2. key=lambda x: abs(x)key 参数用于指定一个函数,这个函数会被用于从每个列表元素中提取一个用于比较的关键字(key)。在这个例子中,lambda x: abs(x) 是一个匿名函数,它接受一个参数 x 并返回 x 的绝对值。这意味着排序将基于元素的绝对值进行。

  3. reverse=True:这个参数指定排序的顺序。默认情况下,sort() 方法会按照从小到大的顺序排序(reverse=False)。当设置为 True 时,排序顺序会变为从大到小。

class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:

        # 首先对nums按照绝对值由大到小进行排序
        nums.sort(key = lambda x:abs(x), reverse = True)

        # 遍历数组nums
        for i in range(len(nums)):
            if nums[i] < 0 and k > 0:
                nums[i] *= (-1)
                k -= 1

        # 如果k还有剩下的且是奇数,此时数组已全是正数,并且数组末尾是最小正数,k可以用多次
        # 那么对数组末尾元素进行取反即可
        if k % 2 == 1: 
            nums[len(nums)-1] *= (-1)

        # 对元素进行求和
        result = sum(nums)
        return result

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值