题目
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximize-sum-of-array-after-k-negations
给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:
选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。
重复这个过程恰好 k 次。可以多次选择同一个下标 i 。
以这种方式修改数组后,返回数组可能的最大和 。
示例 1:
输入:nums = [4,2,3], k = 1
输出:5
解释:选择下标 1 ,nums 变为 [4,-2,3] 。
示例 2:
输入:nums = [3,-1,0,2], k = 3
输出:6
解释:选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2] 。
示例 3:
输入:nums = [2,-3,-1,5,-4], k = 2
输出:13
解释:选择下标 (1, 4) ,nums 变为 [2,3,-1,5,4] 。
提示:
1 <= nums.length <= 104
-100 <= nums[i] <= 100
1 <= k <= 104
解法
-
该题目是一个规律题,需要判断列表中负数的个数n与变换次数的大小k关系:
-
如果n>=k, 只需要将列表中找出从小到大的k个负数进行取反即可(可以先从小到大排序);
-
如果n < k: 在这种情况下即使将所有负数都变换为整数之后还需要进行(k-n)次变换处理;这种时候是对一个非0元素的数组进行操作,分为以下几种情况
- 如果元素数组中有num=0, 那么多余的变换次数只需要对num=0的这个数据进行操作即可,不影响整体的总和;
- 如果元素数组中没有num=0,则需要对数据中最小的正数进行变换操作(注意:是负数变换后的最小正数,又需要从小到大排序一下):
- 剩余的次数是偶数,偶数的操作不会对最小正数产生改变;
- 剩余的次数是奇数,奇数的操作会对最小正数产生改变;
-
python
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
nums.sort() # 从小到大排序
n = len(nums)
neg_nums = 0 # 统计负数的个数
zero_nums = 0 # 是否含有0元素
split_index = 0 # 负数与非零元素的切分点
for i in range(n):
num = nums[i]
if num == 0 and zero_nums == 0:
zero_nums = 1
split_index = i
if num < 0:
neg_nums += 1
if num > 0:
if neg_nums==0:
split_index = 0
elif split_index == 0:
split_index = i
if k <= neg_nums:
for i in range(k):
nums[i] = -1 * nums[i]
if k > neg_nums:
if zero_nums == 1:
for i in range(split_index):
nums[i] = -1 * nums[i]
else:
remain = k - neg_nums
if remain & 1 == 0:
for i in range(split_index):
nums[i] = -1 * nums[i]
else:
if split_index != 0:
for i in range(split_index):
nums[i] = -1 * nums[i]
else:
for i in range(neg_nums):
nums[i] = -1 * nums[i]
nums.sort()
nums[0] = -1 * nums[0]
return sum(nums)
复杂度分析
- 时间复杂度:
- O ( N ∗ l o g N ) O(N*logN) O(N∗logN) 排序花费的时间以及遍历花费的时间
- 空间复杂度:
- O ( 1 ) O(1) O(1)