数组的最小偏移量
难度:
标签:
题目描述
代码结果
运行时间: 181 ms, 内存: 23.2 MB
/**
* Problem: Minimize the deviation in an array using Java Streams
* Approach:
* 1. Transform odd numbers to even by multiplying by 2 and find the minimum element.
* 2. Use a TreeSet to keep sorted elements and find the current deviation.
* 3. Continuously update the max element in the set by dividing it by 2 until all elements are odd.
*/
import java.util.*;
import java.util.stream.Collectors;
public class Solution {
public int minimumDeviation(int[] nums) {
TreeSet<Integer> set = new TreeSet<>();
// Preprocess the array to handle all numbers and create a sorted set
Arrays.stream(nums)
.map(num -> (num % 2 == 1) ? num * 2 : num) // Make odd numbers even
.forEach(set::add);
int minDeviation = Integer.MAX_VALUE;
while (true) {
int max = set.last();
int min = set.first();
minDeviation = Math.min(minDeviation, max - min);
if (max % 2 == 1) break; // Stop when max is odd
set.remove(max);
set.add(max / 2);
}
return minDeviation;
}
}
解释
方法:
首先,为了确保每个数字都可以有效地进行操作(即奇数乘以2变偶数,偶数除以2直到成为奇数),我们将所有奇数都乘以2以统一初始状态。使用最大堆(实际上使用了负数实现最小堆的逆序)来存储这些转换后的数字,以便快速获取当前的最大值。堆的最大值(即负数绝对值最小)代表了当前数组的最大值。我们持续从堆中取出最大值,并尝试将其减半(即最大偶数除以2),然后将新值推回堆中,更新当前的最大值。通过这种方式,我们试图不断缩小数组元素之间的最大差异,即偏移量。每次操作后,都会更新当前的最小偏移量,直到堆顶元素为奇数为止(因为奇数不能再减半)。
时间复杂度:
O(n log(n) log(maxNum))
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在开始时需要将所有奇数乘以2来统一初始状态?这样操作的意义和结果是什么?
▷🦆
在使用最大堆的策略中,为什么选择用负数来实现最小堆的逆序而不是直接使用最大堆?
▷🦆
堆的最大值通过负数的绝对值最小来表示,这种表示方式在算法中如何确保正确性和效率?
▷🦆
你提到每次从堆中取出最大值并尝试将其减半,这个操作如何影响堆的结构和后续操作?
▷