1. 使用TreeSet
class Solution {
public int minimumDeviation(int[] nums) {
if (nums == null || nums.length == 0) return 0;
TreeSet<Integer> set = new TreeSet<>();
// 1. Pre-double all the odd numbers, and numbers only can be smaller.
for (int num : nums) {
if (num % 2 == 0) set.add(num);
else set.add(num * 2);
}
int result = set.last() - set.first();
// 2. When the largest number is odd(can't be smaller), stop iteration.
while (!set.isEmpty() && set.last() % 2 == 0) {
int maxNum = set.last();
set.remove(maxNum);
set.add(maxNum / 2);
// update the smallest deviation
result = Math.min(result, set.last() - set.first());
}
return result;
}
}
好处是可以自动更新最大值last和最小值first,并且作为set,能够自动去掉重复元素(对本题来讲重复元素没有意义)。
使用PriorityQueue
class Solution {
public int minimumDeviation(int[] nums) {
PriorityQueue<Integer> queue = new PriorityQueue<>(Collections.reverseOrder());
int lo = Integer.MAX_VALUE;
// 1. Pre-double all the odd numbers,
// and all numbers can only become smaller(by divided).
for (int num : nums) {
int x = num % 2 == 0 ? num : num * 2;
queue.offer(x);
lo = Math.min(x, lo);
}
int result = queue.peek() - lo;
// 2. Start from the largest number, compare it to the smallest one.
// Divide it by 2 and put it back to the queue. Update the deviation.
// Stop iteration when the largest number is odd(can't be smaller).
while (!queue.isEmpty() && queue.peek() % 2 == 0) {
int x = queue.poll() / 2;
queue.offer(x);
lo = Math.min(lo, x);
result = Math.min(result, queue.peek() - lo);
// Iterator iterator = queue.iterator();
// while (iterator.hasNext()) System.out.print(iterator.next() + " ");
}
return result;
}
}
总体思路一样,最大堆实现,要手动维护最小值lo。
复习知识点:Queue中的重复方法
插入 | 删除 | 查询头部 | |
---|---|---|---|
抛异常 | add() | remove() | element() |
返回 null | offer() | poll() | peek() |
分析
两种方法时间复杂度均为O(N * logM * logN)。其中N代表数据规模,M代表数字大小。N个元素进出优先队列需要logN,而进出的次数与数字的大小M相关(每次重新进入时除以2)。