DAY31 贪心算法part01

理论基础

贪心的本质就是选择每一阶段的局部最优,从而达到全局最优。
贪心算法分为四部

  • 将问题分解为若干子问题
  • 找出适合的贪心策略
  • 求解每个子问题的最优解
  • 将局部最优解堆叠成全局最优解

455.分发饼干

class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        # 先找出胃口最小的孩子,然后对饼干尺寸排序,找出第一个s[j]>=g[i]的饼干,将这块饼干给这个孩子
        g.sort()
        s.sort()
        kids = 0
        for i in range(len(s)):
            if kids < len(g) and s[i] >= g[kids]:
                kids+=1

        return kids

设数组g的长度为n,数组s的长度为m,上述题解分别对g和s进行快排,时间复杂度分别为O(nlogn),O(mlogm),同时分别对g和s进行遍历,分别的时间复杂度为O(n),O(m),所以最终的时间复杂度为O(max(nlogn,mlogm))
空间复杂度,由于快排使用了额外的空间,所以空间复杂度为O(max(logn,logm))(此处的空间复杂度有疑问,暂不确定)

class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g.sort()
        s.sort()
        res, poi, ln = 0,-1,len(s)
        for child in g:
            while poi < ln-1:
                poi+=1
                if s[poi] >= child:
                    res+=1
                    break
        return res

时间复杂度O(n+m)

376.摆动序列

错误代码如下,错因在于我没有考虑题意中说明子序列可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        # 先计算数组的差值数组
        div_nums = list()
        res = 2
        for i in range(1,len(nums)):
            div_nums.append(nums[i]-nums[i-1])
        for i in range(1,len(div_nums)):
            if div_nums[i]*div_nums[i-1] < 0:
                res = i+2
            else:
                break
        return res

正确思路

class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        # 先过滤重复数字(因为重复数字的时候不发生升降)
        filters = [nums[0]]

        for num in nums[1:]:
            if num != filters[-1]:
                filters.append(num)
        # 边界情况下直接返回
        m = len(filters)
        if m == 1:
            return m

        # 记录升降状态以及山峰山谷的个数
        if filters[1] > filters[0]:
            pre = 1
        else:
            pre =-1
        ans = 1
        for i in range(2,m):
            if filters[i]>filters[i-1]:
                cur = 1
            else:
                cur = -1
            if cur == pre:
                continue
            else:
                ans += 1
                pre = cur
        ans+=1
        return ans
class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        n = len(nums)
        pre = 0
        ans = 0
        for i in range(1,n):
            if nums[i] == nums[i-1]:
                continue
            if nums[i] >nums [i-1]:
                if pre !=1:
                    ans +=1
                pre = 1
            else:
                if pre != -1:
                    ans += 1
                pre = -1
        # ans + 1 是为了考虑数组的第一个元素,确保不会因为缺少与之比较的前一个元素而漏掉统计。
        return ans + 1

53.最大子序和

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        """
        维护两个变量
        count  表示当前的累加和
        res    表示全局最大和
        """
        res = nums[0]
        count = 0
        for i in range(len(nums)):
            # 扩展当前子数组
            count += nums[i]
            # 若大于则更新res
            if count > res:
                res = count
            # 若count小于等于0说明当前累加的子数组对整体和是没有增益的,则讲count重置
            if count <= 0:
                count = 0
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值