Leetcode Link: 力扣 (leetcode.cn)

题目

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

选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i

以这种方式修改数组后,返回数组 可能的最大和

解法一

思路

  1. 把尽可能小的,尽可能多的负数变成变成正数(即把绝对值大的负数变成正数)
  2. 只翻转绝对值最小的数

可能情况:

  1. 一个负数没有:只反复翻转绝对值最小的数
  2. 负数个数大于 k 个: 翻转绝对值最大的 k 个
  3. 负数个数小于 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…人家网友写的确实好…