K 次取反后最大化的数组和
难度:
标签:
题目描述
代码结果
运行时间: 22 ms, 内存: 16.2 MB
/*
* 思路:
* 1. 将数组转换为流,按绝对值降序排序。
* 2. 使用forEach和AtomicInteger来处理负数并递减k。
* 3. 如果k为奇数,找到最小绝对值数并进行翻转。
* 4. 使用stream.sum()来计算最终数组的和。
*/
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
public class MaximizeArraySum {
public int largestSumAfterKNegations(int[] nums, int k) {
AtomicInteger remainingK = new AtomicInteger(k);
int[] sortedNums = IntStream.of(nums)
.boxed()
.sorted((a, b) -> Integer.compare(Math.abs(b), Math.abs(a)))
.mapToInt(Integer::intValue)
.toArray();
sortedNums = IntStream.of(sortedNums)
.map(n -> {
if (n < 0 && remainingK.get() > 0) {
remainingK.getAndDecrement();
return -n;
}
return n;
}).toArray();
int min = Arrays.stream(sortedNums).min().orElse(0);
if (remainingK.get() % 2 == 1) {
sortedNums[Arrays.binarySearch(sortedNums, min)] = -min;
}
return Arrays.stream(sortedNums).sum();
}
}
解释
方法:
此题解采用最小堆的策略来达到最大化数组和。首先,将数组中的所有元素插入到一个最小堆中,这样可以快速地获取到数组中的最小值。随后,进行k次操作,每次操作都是取出当前堆中的最小元素(这个元素是对当前数组和影响最负面的),然后将其值取反后放回堆中。这样做的目的是尽可能地减少数组中负值的影响或增加正值的影响。经过k次这样的操作后,堆中的所有元素即为修改后的数组,最后计算这些元素的和即为所求的最大数组和。
时间复杂度:
O((n+k) log n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在选择数组中的元素取反时倾向于使用最小堆而不是其他数据结构如最大堆或者数组本身?
▷🦆
在进行k次取反操作后,如果最小元素已经是正数,继续取反是否会降低数组的总和?
▷🦆
该算法处理全为正数或全为负数的数组时,其行为和效果是否有明显的不同?
▷🦆
执行完所有k次操作后直接计算堆中所有元素的和,这里是否考虑到堆的结构可能导致部分元素位置发生变化,从而影响和的计算?
▷