算法训练Day34 贪心算法专题 | LeetCode1005.K次取反后最大化的数组和 ;134.加油站;135.分发糖果(不要两头兼顾,一边一边处理)

前言:

算法训练系列是做《代码随想录》一刷,个人的学习笔记和详细的解题思路,总共会有60篇博客来记录,计划用60天的时间刷完。 

内容包括了面试常见的10类题目,分别是:数组,链表,哈希表,字符串,栈与队列,二叉树,回溯算法,贪心算法,动态规划,单调栈。

博客记录结构上分为 思路,代码实现,复杂度分析,思考和收获,四个方面。

如果这个系列的博客可以帮助到读者,就是我最大的开心啦,一起LeetCode一起进步呀;)

目录

LeetCode1005.K次取反后最大化的数组和 

1. 思路

2. 代码实现

3. 复杂度分析

4. 思考与收获

Leetcode134. 加油站

方法一: 暴力解法

1. 思路

2. 代码实现

3. 复杂度分析

4. 思考与收获

方法二:宏观的贪心算法

1. 思路

2. 代码实现

3. 复杂度分析

4. 思考与收获

方法三:贪心解法

1. 思路

2. 代码实现

3. 复杂度分析

4. 思考与收获

总结

Leetcode135. 分发糖果

1. 思路

2. 代码实现

3. 复杂度分析

4. 思考与收获


LeetCode1005.K次取反后最大化的数组和 

链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)

1. 思路

本题思路其实比较好想了,如何可以让数组和最大呢?

贪心的思路,局部最优:让绝对值大的负数变为正数,当前数值达到最大,整体最优:整个数组和达到最大。

局部最优可以推出全局最优。

那么如果将负数都转变为正数了,K依然大于0,此时的问题是一个有序正整数序列,如何转变K次正负,让 数组和 达到最大。

那么又是一个贪心:局部最优:只找数值最小的正整数进行反转,当前数值可以达到最大(例如正整数数组{5, 3, 1},反转1 得到-1 比 反转5得到的-5 大多了),全局最优:整个 数组和 达到最大。

虽然这道题目大家做的时候,可能都不会去想什么贪心算法,一鼓作气,就AC了。

我这里其实是为了给大家展现出来 经常被大家忽略的贪心思路,这么一道简单题,就用了两次贪心!

那么本题的解题步骤为:

  • 第一步:将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小
  • 第二步:从前向后遍历,遇到负数将其变为正数,同时K--
  • 第三步:如果K还大于0,那么反复转变数值最小的元素,将K用完
  • 第四步:求和

2. 代码实现

# time:O(NlogN);space:O(N)
class Solution(object):
    def largestSumAfterKNegations(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        # 将数组nums按照绝对值大小,从大到小排序
        sortedNums = sorted(nums,key=abs,reverse=True)
        index = 0
        # 从大的开始,把负数变成正数
        while k>0 and index<len(nums):
            if sortedNums[index]<0:
                sortedNums[index] *= -1
                k -= 1
            index += 1
        # 如果所有数都变成非负数之后,K仍为正数
        # 就针对最后一个绝对值最小的数,把K都用完
        if k>0:
            sortedNums[-1] *= (-1)**k
        return sum(sortedNums)

3. 复杂度分析

  • 时间复杂度:O(logN)

    其中N为数组nums的长度,首先需要对数组nums进行排序的时间复杂度为O(NlogN);然后需要遍历一遍数组,从大到小把尽可能多的负数变成正数,O(N),还有sum操作,复杂度O(N),总体时间复杂度O(NlogN);

  • 空间复杂度:O(N)

    其中N为nums的长度,sorted排序新建了一个数组,O(N);

4. 思考与收获

  1. 空间复杂度上还可以继续优化,不用sorted,而用sort,就会在原数组上进行操作,不会新建一个数组,复杂度可以降低为O(1),代码如下:

    # time:O(NlogN);space:O(1)
    class Solution(object):
        def largestSumAfterKNegations(self, nums, k):
            """
            :type nums: List[int]
            :type k: int
            :rtype: int
            """
            # 将数组nums按照绝对值大小,从大到小排序
            nums.sort(key=abs,reverse=True)
            index = 0
            # 从大的开始,把负数变成正数
            while k>0 and index<len(nums):
                if nums[index]<0:
                    nums[index] 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值