贪心算法

一、跳跃游戏-(leetcode55)

贪心策略是我们每次都选取最优的策略,然后前面已经选好了的就不用管了。

这个贪心的方法是,我们使用一个变量reach 保存当前能达到的最后位置索引,那么在每个位置的时候判断这个位置能不能到达,即位置的索引大于这个reach,说明前面无论怎么走也走不到这个位置,返回False。如果这个位置可以到达,要维护一下这个reach,更新策略是:当前索引位置+这个数字表示能向右走多少步,这个代表了到达当前位置的时候向右边能到达 的最远距离,在这个最远距离以内的任何位置都能到,因为每次跳的步数可以变小的。进行了一次循环后,每个位置都能到达,结果可以返回True.

时间复杂度o(n) 空间复杂度o(1)

我写的代码
class Solution:
    def canJump(self, nums: List[int]) -> bool:
        
        maxlen=nums[0]
        for i in range(len(nums)):
            if maxlen< i:
                return False
            max1=i+nums[i]
            if max1>maxlen:
                maxlen=max1
        return True
官网的代码,比我的代码写的好
class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        reach = 0
        for i, num in enumerate(nums):
            if i > reach:
                return False
            reach = max(reach, i + num)
        return True

贪心和DP的比较:

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来最好的选择。也就是说,不从整体最优上加以考虑,他所作出的是在某种意义上的局部最优解。贪心算法和动态规划算法都是由局部最优导出全局最优,这里不得不比较下二者的区别。

贪心算法:
1.贪心算法中,作出的每步贪心决策都无法改变,因为贪心策略是由上一步的最优解推导下一步的最优解,而上一步之前的最优解则不作保留;
2.由(1)中的介绍,可以知道贪心法正确的条件是:每一步的最优解一定包含上一步的最优解。

动态规划算法:
1.全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解
2.动态规划的关键是状态转移方程,即如何由以求出的局部最优解来推导全局最优解;
3.边界条件:即最简单的,可以直接得出的局部最优解。
参考:
原文:https://blog.csdn.net/fuxuemingzhu/article/details/83504437 

二、跳跃游戏-leetcode45

贪心策略:

我们每次贪心的找在自己当前能到达的几个位置里面,跳到哪个位置的时候,在下一步能跳的最远。然后,我们当前步就跳到这个位置上去,所以我们在这一步的跳跃时,给下一步留下了最好的结果。

所以,使用一个cur表示当前步能到达的最远位置,使用pre表示上一次能到达的最远位置。所以,我们应该遍历在上一步的覆盖范围内,当前能跳的最远位置来更新cur。一个节省计算资源的方式是,保存以前已经检查了的位置为Pos,这样每次检查的范围是pos~pre。

class Solution(object):
    def jump(self, nums):
        cur = 0
        N = len(nums)
        count = 0
        pos = 0
        while cur < N - 1:
            count += 1
            pre = cur
            while pos <= pre:
                cur = max(cur, pos + nums[pos])
                pos += 1
        return count

三、划分字母区间

map 加 贪心 简单有效 时间复杂度 n 空间复杂度 n

第一步:

先遍历一遍,用字典存储每个字符最后的位置。
第二步:
从第一个字符开始遍历,每获取一个字符就该字符最后一次出现的位置索引定为当前片段的最后位置,
在达到该位置之前,继续寻找更靠后的最后位置,若达到最后位置之前都没有发现更靠后的最后位置,则将当前最后位置作为一个片段的末尾,

class Solution:
    def partitionLabels(self, S: str) -> List[int]:
        dic = {}
        for i ,s1 in enumerate(S):
            dic[s1] = i
        result = []
        cur = dic[S[0]]
        for i ,s1 in enumerate(S):
            if dic[s1] > cur :
                cur = dic[s1]
            if i == cur :
                result.append(cur+1-sum(result))
        return result

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值