Featured image of post 1005. K 次取反后最大化的数组和

1005. K 次取反后最大化的数组和

题目描述

给你一个整数数组 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

解法一:贪心

如下是错误代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func largestSumAfterKNegations(nums []int, k int) int {
    n := len(nums)
    sort.Ints(nums)

    idx := 0
    for k > 0 && idx < n {
        if nums[idx] < 0 {
            nums[idx] = -nums[idx]
        } else {
            if k&1 == 1 {
                nums[idx] = -nums[idx]
            }
            break
        }
        k--
        idx++
    }

    res := 0
    for _, v := range nums {
        res += v
    }
    return res
}

上面代码错误的原因是不能通过如下测试用例

1
2
3
4
nums = [-8,3,-5,-3,-5,-2]
k = 6
预期结果:22
实际结果:20

修改后的代码如下,依旧没有通过

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func largestSumAfterKNegations(nums []int, k int) int {
    n := len(nums)
    sort.Ints(nums)

    idx := 0
    for k > 0 && idx < n {
        if nums[idx] < 0 {
            nums[idx] = -nums[idx]
        } else {
            sort.Ints(nums)
            if k&1 == 1 {
                nums[0] = -nums[0]
            }
            break
        }
        k--
        idx++
    }

    res := 0
    for _, v := range nums {
        res += v
    }
    return res
}

上面的代码没有通过如下测试用例

1
2
3
4
nums = [-4, -2, -3]
k = 4
输出:9
预期结果:5

错误的原因是当 k > len(nums) 时没有使用完 k

修改后的代码如下,如下代码通过了所有测试用例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
func largestSumAfterKNegations(nums []int, k int) int {
    n := len(nums)
    sort.Ints(nums)

    idx := 0
    for k > 0 && idx < n {
        if nums[idx] < 0 {
            nums[idx] = -nums[idx]
        } else {
            break
        }
        k--
        idx++
    }
    sort.Ints(nums)
    if k > 0 {
        // all elements in nums now is greater than or equal zero
        if k&1 == 1 {
            nums[0] = -nums[0]
        }
    }

    res := 0
    for _, v := range nums {
        res += v
    }
    return res
}

官方题解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
func largestSumAfterKNegations(nums []int, k int) (ans int) {
    freq := map[int]int{}
    for _, num := range nums {
        freq[num]++
        ans += num
    }
    for i := -100; i < 0 && k != 0; i++ {
        if freq[i] > 0 {
            ops := min(k, freq[i])
            ans -= i * ops * 2
            freq[-i] += ops
            k -= ops
        }
    }
    if k > 0 && k%2 == 1 && freq[0] == 0 {
        for i := 1; i <= 100; i++ {
            if freq[i] > 0 {
                ans -= i * 2
                break
            }
        }
    }
    return
}

func min(a, b int) int {
    if a > b {
        return b
    }
    return a
}

复杂度分析

  • 时间复杂度:O(n+C),其中 n 是数组 nums 的长度,C 是数组 nums 中元素的范围,本题中 C=201。 我们需要 O(n) 的时间使用桶或哈希表统计每个元素出现的次数,随后需要 O(C) 的时间对元素进行操作。

  • 空间复杂度:O(C),即为桶或哈希表需要使用的空间。

Licensed under CC BY-NC-SA 4.0
最后更新于 2023/05/17 21:11:05
comments powered by Disqus
Built with Hugo
主题 StackJimmy 设计