irpas技术客

代码随想录NO32 | 贪心算法_Leetcode 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果_Rocket,Qian

未知 2146

贪心算法_Leetcode 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果

今天是贪心算法的第三天的题了!

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

给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:

选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。

重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 以这种方式修改数组后,返回数组 可能的最大和 。

解题步骤:

将数组按照绝对值大小从大到小排序,注意要按照绝对值的大小从前向后遍历,遇到负数将其变为正数,同时K–如果K还大于0,那么反复转变数值最小的元素,将K用完求和 class Solution: def largestSumAfterKNegations(self, nums: List[int], k: int) -> int: nums = sorted(nums, key = abs, reverse= True) # 按绝对值从大到小排序 for i in range(len(nums)): if k > 0 and nums[i] < 0: nums[i] *= -1 k -= 1 if k > 0: nums[-1] *= (-1)**k return sum(nums)

134. 加油站

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gas 和 cost ,如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则保证它是唯一 的。

1.暴力解法: 遍历每一个加油站为起点的情况,模拟一圈。 如果跑了一圈,中途没有断油,而且最后油量大于等于0,说明这个起点是ok的。 暴力的方法思路比较简单,但代码写起来也不是很容易,关键是要模拟跑一圈的过程。 for循环适合模拟从头到尾的遍历,而while循环适合模拟环形遍历,要善于使用while!

2.贪心算法 首先如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明各个站点的加油站 剩油量rest[i]相加一定是大于等于零的。 每个加油站的剩余量rest[i]为gas[i] - cost[i]。 i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,起始位置从i+1算起,再从0计算curSum。

局部最优:当前累加rest[j]的和curSum一旦小于0,起始位置至少要是j+1,因为从j开始一定不行。全局最优:找到可以跑一圈的起始位置。

class Solution: def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int: if sum(gas) < sum(cost) : return -1 else: cursum = 0 start = 0 totalsum = 0 for i in range(len(gas)): cursum += gas[i] - cost[i] totalsum += gas[i] - cost[i] if cursum < 0: start = i + 1 cursum = 0 if totalsum < 0 : return -1 return start

135. 分发糖果

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的最少糖果数目。

思路: 这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,如果两边一起考虑一定会顾此失彼。

先确定右边评分大于左边的情况(也就是从前向后遍历)

此时局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果

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

如果ratings[i] > ratings[i - 1] 那么[i]的糖 一定要比[i - 1]的糖多一个,所以贪心:candyVec[i] = candyVec[i - 1] + 1

再确定左孩子大于右孩子的情况(从后向前遍历)

class Solution: def candy(self, ratings: List[int]) -> int: candy_num = [1] * len(ratings) # 从左往右遍历 for i in range(1,len(ratings)): if ratings[i] > ratings[i-1]: candy_num[i] = candy_num[i-1]+1 # 从右往左 for j in range(len(ratings)-2, -1,-1): if ratings[j] > ratings[j + 1]: candy_num[j] = max(candy_num[j] , candy_num[j+1] + 1) return sum(candy_num)

今天的贪心还是有点难度的啊,虽然想通后,代码很简单!


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #代码随想录NO32 #贪心算法_Leetcode #134 #加油站 #135 #分发糖果