代码随想录算法训练营第34天| 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果

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


代码思路

有点堆屎山的感觉。。。不可取啊

class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        n = 1
        nums = sorted(nums)
        
        for i in range(len(nums)):
            if n <= k: 
                if nums[i] < 0:
                    nums[i] = -nums[i]
                    n += 1
                    if i == len(nums)-1 and n <= k:
                        nums[i] = -nums[i]
                elif nums[i] == 0:
                    return sum(nums)
                else:
                    nums[i] = ((-1)**((k - n)+1)) * nums[i]
                    if i > 0 and abs(nums[i-1]) < abs(nums[i]) and n == k:
                        nums[i-1] = -nums[i-1]
                        nums[i] = abs(nums[i])
                    break
            else:
                return sum(nums)
        return sum(nums)

134. 加油站:


代码思路

超时,不知道为啥。。。贪心思路:当一个区间内的和为负数,则这个区间都不可能为begin。
贪心新想法:先暴力,不能剪枝则看看有没有可以抽象出“状态”,看看重复计算的状态,然后剪枝,能剪枝则为dp,不能则需要我们发现一些隐藏较深的规律,从而减少一些冗余的计算。(找不到重复计算就找冗余计算(也就是可以跳过的))

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        sum = 0
        begin = 0
        i = 0
        while i < len(gas):
            sum += gas[i]
            sum -= cost[i]

            if sum < 0:
                sum = 0

                if i == begin - 1:
                    return -1
                if begin == len(cost) - 1:
                    return -1
                if i == len(cost) - 1:
                    return -1
                i += 1
                begin = i

            else:
                if i == begin - 1:
                    return begin
                if begin == 0 and i == len(cost) - 1:
                    return 0
                i += 1

            if i > len(gas) - 1 and begin != 0:
                i = 0
        return begin

135. 分发糖果:


代码思路

第一、当从左遍历,我们确保了当右边孩子的得分比左边孩子(右孩子为当前孩子)高,右边的孩子分到的糖果更多。
第二、当从左遍历,当右孩子的得分比左孩子低的时候,右孩子默认得最低分1,尽管左孩子可能也是1分,不符合规定。

第三、当从右遍历时,当左孩子的得分比右孩子高的时候(左孩子为当前孩子),我们要把左孩子的分数做得比右孩子要大。但是这可能会可能也会使得左孩子的糖果变少,毕竟我只要大于右孩子的糖果就行了。所以此时当左孩子本身比右孩子的糖果多的时候,就不需要处理了。因为左孩子的糖果下限时右孩子的糖果+1。

第四、当从右遍历时,那当左孩子的得分比右孩子低的时候咋办呢?(左孩子为当前孩子)答案是不用管。为什么不用管?因为从左遍历完后,本身就已经符合规定,所以我们只要确保不减少左孩子的糖果就ok。

为什么不能使左孩子的糖果变少?因为左孩子原本的糖果之所以多,是因为他比更左的孩子得分高,当减少了他的糖果,就会破坏刚开始左遍历的结果。

以上逻辑还是比较混乱。毕竟这是一道难题。

class Solution:
    def candy(self, ratings: List[int]) -> int:
        result_list = [0 for i in range(len(ratings))]
        result_list[0] = 1
        # 左规则:即当左边小于右边,右边要比左边多1.当左边大于等于右边,而左边为1时,此时就搞不了。所以就不管了
        for i in range(1, len(ratings)):
            if ratings[i] > ratings[i-1]:
                result_list[i] = result_list[i-1] + 1
            else:
                result_list[i] = 1
        # 右规则:即当右边小于左边,左边要比右边多1.当右边大于等于左边,而右边为1时,此时就搞不了。所以就不管了
        for i in list(range(0, len(ratings) - 1))[::-1]:
            if ratings[i] > ratings[i+1]:
                result_list[i] = max(result_list[i], result_list[i+1] + 1)            
        return sum(result_list)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值