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

你可能感兴趣的:(贪心算法,python)