力扣刷题-python-贪心算法-1(贪心算法简介、题目)

1.贪心算法

贪心算法是每一小步都选最优,从而导致结果最优
贪心算法基本都是常识问题,并且和其他混合在一起。
就想刚刚我做了一道题,做完之后,我满脸问号,我这是用了贪心?没感觉
所以不用太多想贪心的问题,正常做就好。

2.简单中等题目(455、376、53、122、55、1005、134、860、406、452)

455. 分发饼干 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g.sort()
        s.sort()
        res=0
        #将饼干从小到大依次发给同学,如果小于同学的胃口不给,再在下面找到一个大的给。
        #哎哎有贪心的感觉了
        for i in s:
            if res< len(g) and i>=g[res]:res+=1
        return res

376. 摆动序列 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        cursub, res = 0, 1 
        for i in range(len(nums)-1):
            suber = nums[i+1]-nums[i]  #cursub代表选定的数,如果与他的乘积大于1 不选
            if cursub*suber<=0 and suber!=0:
                res+=1
                cursub=suber  #前一个差数
        return res

53. 最大子数组和 - 力扣(LeetCode) (leetcode-cn.com)

我发现贪心的每道题都不一样,每道题都有他的独到之处,很考验观察能力。

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
         #连续的子数组 ,如果连续数组相加为负的,那么再相加,只会连累后面的数组,所以要从新开始
         count=0
         res=-float(inf)
         for i in range(len(nums)):
             count+=nums[i]
             if count> res: res=count
             if count<=0 :count=0  #如果前面数相加为负的,从新开始,conut清零
         return res

122. 买卖股票的最佳时机 II - 力扣(LeetCode) (leetcode-cn.com)
贪心啊贪心,难的还是数学想法,难喽

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
          #两天相差小于0的不要 只要大于0的
          res= 0 
          for i in range(1,len(prices)):
              res+= max(prices[i]-prices[i-1],0)
          return res

55. 跳跃游戏 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        '''
        #用curval表示 某个位置值和 curval-1 最大一个
        #如果curval 在某一位小于0 说明跳不过去
        curval=1
        for i in nums:
           if curval-1 <0: return False
           curval = max(curval-1,i) 
        return True
        '''

        #反过来想 可以用curval 表示某个位置 i+num[i] 和curval 最大值
        #如果他大于nums长度减-1 说明能够到达最后
        curval = i=0
        while i<= curval:
            curval = max(i+nums[i],curval)
            if curval >=len(nums)-1:return True
            i+=1
        return False

55. 跳跃游戏 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def jump(self, nums: List[int]) -> int:
        #
        jumpval=0
        start, ender, res =0, 1, 0
        while ender<len(nums):
           for i in range(start,ender):
               if  i+nums[i]>= jumpval: jumpval = i+nums[i]  # 能跳到最远的距离
           start=ender                                       #下一次起跳点范围开始的格子
           ender=jumpval+1                                   #下一次起跳点范围结束的格子
           res+=1                                            #跳跃次数
        return res   

1005. K 次取反后最大化的数组和 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        '''
        nums.sort()
        res=0
        for i in range(len(nums)):
            if k>0:
               if nums[i]<0:
                   k-=1
                   res-=nums[i]
               elif k%2:
                   if i>0 and -nums[i-1]<nums[i]:
                         res+=2*nums[i-1]
                         res+=nums[i]
                   else:       
                         res-=nums[i]
                   k=0
               else:res+=nums[i]
            else:res+=nums[i]
        if k and k%2:res+=2*nums[-1]
        return res
        '''
        #自己想法还是太复杂了
        #直接用绝对值的排序
        nums.sort(key=abs,reverse=True)    #按照绝对值 将nums排序 这个对最后k在负值没有取完有好处
        res=0 
        for i in range(len(nums)):
            if k>0 and nums[i]<0:
                   nums[i]*=-1
                   k-=1
        if k>0 and k%2:nums[-1]*=-1
        return sum(nums)

134. 加油站 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        #result = gas- cost
        #如果所有的result和为大于0 说明可以走的回去
        #从哪里开始,可以用i=0 试探找到最小值点 如果这个点小于0 就从i+1 开始
        minres =float(inf)
        res= resindex =0
        for i in range(len(gas)):
             res +=  gas[i] - cost[i]
             if res< minres: 
                 minres=res  
                 resindex=i  #保存最小情况索引
        if res<0 : return -1
        else:
            if minres>=0: return 0
            else:return resindex+1

860. 柠檬水找零 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def lemonadeChange(self, bills: List[int]) -> bool:
        #5 不需要 10 需要前一个5 20需要前面右1个10和一个5
        num5=0
        num10=0
        for i in bills:
             if not i-5: num5+=1
             elif not i-10:
                 num10+=1
                 num5-=1
             else:
                 if num10-1<0:num5-=2  #这里用了贪心,优先给10元的
                 else:num10-=1
                 num5-=1
             if num5<0 or num10<0:return False
        return True

406. 根据身高重建队列 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
        #首先按照身高从高到低排序
        people.sort(key = lambda x:(-x[0],x[1]))  #首先按照身高排序 先按照身高从大到小,如果身高相同,在按照k从到大排列
        res=[]
        #然后从这个序列依次取出,按照k的值插入  因为身高低的不会影响后面的k的值
        for i in people: res.insert(i[1],i)
        return res

452. 用最少数量的箭引爆气球 - 力扣(LeetCode) (leetcode-cn.com)

class Solution:
    def findMinArrowShots(self, points: List[List[int]]) -> int:
        points.sort()
        #选中一个点xend 看下一个是否在这个范围内,直至不能满足要求
        fxend=points[0][1]
        res=1
        for i in points[1:]:
            if i[0]>fxend: 
                fxend=i[1]
                res+=1
            else:
                if i[1]<fxend: fxend=i[1]
        return res

3.困难题目(135)

135. 分发糖果 - 力扣(LeetCode) (leetcode-cn.com)
两次贪心策略
一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
每次用py做完都想说,python yyds。

class Solution:
    def candy(self, ratings: List[int]) -> int:
        #分两次 一次从左向右遍历, 保证右边大于的左边 只要右边大于左边 res[i]=res[i-1]+1
        #另外一次从右向左遍历,保证左边大于右边 只要左边大于右边 res[i]=res[i+1]+1 
        #但是要和第一次遍历情况中和,也就是两个都要包含 所以取最大值
        res =[1 for _ in ratings]
        for i in range(1,len(ratings)):       #从左向右遍历
             if ratings[i]>ratings[i-1]:
                 res[i]=res[i-1]+1

        for i in range(len(ratings)-2,-1,-1): #从右向左遍历
            if ratings[i]>ratings[i+1]:
                res[i]=max(res[i+1]+1,res[i])

        return sum(res)

4.总结

感觉我再做贪心算法之类的题,我就要疯掉了,虽然做出来感觉不难,但是去想的过程太煎熬了,就是因为没有固定的格式。。。
好吧,还有10道左右,明天再给自己一天时间把。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值