问题分析
问题描述了对一个整数数组nums进行操作的场景。可以选择某个下标i并将nums[i]替换为-nums[i],操作可以进行k次。需要求出通过这种方式修改数组后,能够得到的数组元素总和的最大值。
问题详解
排序:首先,对数组进行排序。这样,我们可以更容易地识别出哪些元素需要被取反以增加总和。
取反操作:从数组的开始,对每个负数进行取反操作,直到操作次数用完。这样做是因为负数取反后会变成正数,从而增加总和。
处理剩余操作:如果操作次数有剩余,我们需要考虑如何处理。如果剩余操作次数为奇数,我们可以选择取反最小的正数或零,因为这样做对总和的影响最小。
计算总和:最后,计算数组的总和,这就是我们通过有限操作能得到的最大和。
代码
def solution(nums: list, k: int) -> int:
# 1. 对数组进行排序
nums.sort()
# 2. 从最小的负数开始,依次取反,直到 k 次操作用完
for i in range(len(nums)):
if nums[i] < 0 and k > 0:
nums[i] = -nums[i]
k -= 1
# 3. 如果 k 次操作后还有剩余操作次数,处理剩余操作
if k > 0:
# 如果剩余操作次数是奇数,取反最小的正数(或零)
if k % 2 == 1:
nums.sort()
nums[0] = -nums[0]
# 4. 计算数组的总和
return sum(nums)
if name == 'main':
print(solution(nums=[-4, 2, 3], k=1) == 9)
print(solution(nums=[-3, -1, 0, 3], k=3) == 7)
print(solution(nums=[-2, -3, -1, 5, -4], k=2) == 9)
代码详解
1.排序操作
nums.sort()对输入的整数数组nums进行排序,默认是升序排序。这一步使得负数集中在数组的左侧,方便后续操作。
2.负数取反操作
通过for循环for i in range(len(nums)):遍历数组。
条件判断if nums[i] < 0 and k > 0:检查当前元素是否为负数且还有剩余操作次数k。如果满足条件,则将该负数取反nums[i] = -nums[i],并将k减 1。
3.处理剩余操作次数
当k > 0时,表示还有操作次数剩余。
条件判断if k % 2 == 1:检查剩余操作次数是否为奇数。如果是奇数,需要取反最小的正数(或零)。通过nums.sort()重新对数组排序,此时数组中的最小正数(或零)在最左侧,然后nums[0] = -nums[0]将其取反。
4.计算总和
return sum(nums)计算经过操作后数组元素的总和并返回。
5.主程序测试
在if name == 'main':部分,对solution函数进行了测试,分别传入了题目中给出的三组测试数据,验证函数返回值是否正确。
知识总结
在使用豆包MarsCode AI 刷题的过程中,我总结了以下几个新知识点:
排序的重要性: 在处理涉及多个元素的问题时,排序往往是简化问题的关键步骤。通过排序,我们可以更容易地找到需要优先处理的元素。
贪心算法的应用: 本题中,我们采用了贪心策略,即每次选择当前最优的操作(取反最小的负数)。这种策略在很多优化问题中都非常有效。
边界条件的处理: 在处理剩余操作次数时,我们需要考虑奇偶性,以确保最终结果的正确性。
工具运用
豆包MarsCode AI刷题功能提供了丰富的题目资源和智能化的指导,可以帮助用户更高效地学习。结合其他学习资源,如在线教程、视频讲解等,可以进一步丰富学习体验,提高学习效果。