LeetCode周赛217D:5616. 数组的最小偏移量
概述: 把所有数都变成自己可变化范围的最大值, 然后不断缩小当前的最大值.
首先: 一个数的变化范围有限, 比如所有的奇数都只能做一次乘 2 操作, 偶数可以做若干次除以 2 的操作.
比如 3 可以变成 3, 6; 4 可以变成 1, 2, 4; 12 可以变成 3, 6, 12…
数值可以双向变化不好处理, 我们先变成单向的: 把所有数都变成自己可变化范围的最大值.
那么现在剩下的操作就只有把数缩小了.
而偏移量 = 最大值 - 最小值, 所以我们要做的就是缩小最大值. (缩小其他数值也无法优化偏移量)
那么操作就是: 不断缩小当前的最大值即可, 直到不能缩小, 期间不断维护答案.
Java 使用 T r e e S e t TreeSet TreeSet 或者 P r i o r i t y Q u e u e PriorityQueue PriorityQueue 都可以动态维护最大值.
空间复杂度 O ( N ) O(N) O(N), 时间复杂度 O ( N l o g N l o g N ) O(NlogNlogN) O(NlogNlogN)
最多循环 N l o g N NlogN NlogN 次, 因为一个数除以 2 的次数是 l o g N logN logN; 每次循环是 l o g N logN logN.
优先队列
class Solution {
public int minimumDeviation(int[] nums) {
TreeSet<Integer> set = new TreeSet<>();
int ans = Integer.MAX_VALUE;
int len = nums.length;
for(int i = 0; i < len ; i++){
set.add((nums[i] % 2) == 0 ? nums[i] : nums[i] * 2);
}
// 直到奇数停下
// ans > 0 &&
while(set.last() % 2 == 0){
int mx = set.last();
set.remove(mx);
set.add(mx / 2);
ans = Math.min(ans, set.last() - set.first());
}
return ans;
}
}
作者:MMMMMModddl 题解: 有序集合/优先队列 循环处理Sky