leetcode:1005.k次取反后最大化的数组和

题目

来源:力扣(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(NlogN) 排序花费的时间以及遍历花费的时间
  • 空间复杂度:
    • O ( 1 ) O(1) O(1)

おすすめ

転載: blog.csdn.net/uncle_ll/article/details/121710115