将数组和减半的最少操作次数
难度:
标签:
题目描述
代码结果
运行时间: 184 ms, 内存: 27.2 MB
/*
* 题目思路:
* 1. 使用流计算初始数组的总和。
* 2. 用一个优先队列(最大堆)来存储所有数字,按从大到小排序。
* 3. 每次从堆顶取出最大的数字,将其减半后再放回堆中,
* 并更新当前数组和和减少的和,直到减少的和达到至少一半的初始和。
* 4. 返回操作的次数。
*/
import java.util.PriorityQueue;
import java.util.stream.IntStream;
public class SolutionStream {
public int minOperations(int[] nums) {
double totalSum = IntStream.of(nums).asDoubleStream().sum();
PriorityQueue<Double> maxHeap = new PriorityQueue<>((a, b) -> Double.compare(b, a));
IntStream.of(nums).asDoubleStream().forEach(maxHeap::offer);
double halfSum = totalSum / 2;
double reducedSum = 0;
int operations = 0;
while (reducedSum < halfSum) {
double maxVal = maxHeap.poll();
double halfVal = maxVal / 2;
reducedSum += halfVal;
maxHeap.offer(halfVal);
operations++;
}
return operations;
}
}
解释
方法:
题解采用贪心策略,优先选择能对总和减少最大影响的数进行操作。首先计算数组的初始总和。数组进行排序后,从最大的数开始,每次选择当前最大的数,将其减半并累加操作次数,直到减半的累计值达到或超过原数组总和的一半。此外,使用一个双端队列(deque)来存储每次操作后生成的新数值,保证每次都能从当前可选的数中挑选最大的进行操作。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
在使用双端队列(deque)存储减半数值时,如何保证队列中元素始终按照从大到小的顺序排列?
▷🦆
如果数组中包含多个相同的最大值,题解中的策略会如何选择进行操作,是否会影响最终的操作次数?
▷🦆
题解中提到`每次操作只将一个数减半`,为什么选择每次只操作一个数,而不是同时对多个数进行操作?
▷🦆
在题解的循环条件中,`while sub < total/2 and nums`表明循环直到减少的总和达到原总和的一半或者数组为空。数组为空但累计减少的总和未达到目标时,如何处理?
▷