Leetcode Link: 力扣 (leetcode.cn)
题目
给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:
选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。
重复这个过程恰好 k 次。可以多次选择同一个下标 i 。
以这种方式修改数组后,返回数组 可能的最大和 。

解法一
思路:
- 把尽可能小的,尽可能多的负数变成变成正数(即把绝对值大的负数变成正数)
- 只翻转绝对值最小的数
可能情况:
- 一个负数没有:只反复翻转绝对值最小的数
- 负数个数大于 k 个: 翻转绝对值最大的 k 个
- 负数个数小于 k 个:翻转所有的负数,然后一直翻转绝对值最小的数(翻转所有负数后变成情况 1)
题解:
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
fs_idx = [] # 负数在nums里索引
fs_val = [] # 负数值
minimal_idx = -1 # 非负最小值在nums里索引
minimal_val = float('inf') #非负最小值
for idx, val in enumerate(nums):
if val < 0: # 找所有的负数和对应的索引
fs_idx.append(idx)
fs_val.append(val)
if minimal_val > abs(val): # 找最小非负数及索引
minimal_idx = idx
minimal_val = abs(val)
while(k>0): # 开始翻转
k -= 1
if len(fs_idx) !=0: # 有负数时找到当前的最小值(fs_val里全是负数)并翻转,然后在待选里删除它
tar_idx = fs_val.index(min(fs_val))
nums[fs_idx[tar_idx]] = -nums[fs_idx[tar_idx]]
fs_val.pop(tar_idx)
fs_idx.pop(tar_idx)
else: # 反之只翻转最小的非负数
nums[minimal_idx] = -nums[minimal_idx]
return sum(nums)傻逼了,排个序不就完事了嘛… 我尼玛… 搞得这么复杂 下面抄的网友的,我自己最后还是没写出来… 其实主要关注到本题重点在于绝对值就可以了…
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
# 将nums按绝对值从大到小排列
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 #取nums最后一个数只需要写-1
return sum(nums)启发和联系
emmmm…人家网友写的确实好…