Hard级别的新题:给定整数数组nums, 你每次可以对其中任意的数进行如下操作:
(1) 如果元素是奇数,则你可以把它乘以2
(2)如果元素是偶数,则你可以把它除以2
两种操作可以进行任意多次,变换后的数组的差定义为任意两个元素的差的最大值。求最小的数组差。
数据范围:2<=nums.size()<=100000, 1 <= nums[.]<=1000000000
例如: nums[] = {1, 2, 3, 4}答案是1, 因为我们可以把1乘以2, 把4除以2,数组变为{2, 2, 3, 2},差为1。
分析:求的是数组的最大值减去最小值的差的最小值。我们先把数组里奇数都乘以2,如此以后所有的数都是偶数,而且所有的数都只能进行操作(1)了,也只能减小了。
然后我们枚举最大值——用multiset或者堆。对于某个最大值,如果要使得数组差值尽可能小,最小值是不能减小的——显然我们希望最小值尽可能大,才能够接近最大值,所以我们就用当前最大值减最小值作为一个可行解。
如果最大值是偶数,则把它除以2,再扔回去——注意下次取最大值可能已经变了,因为mutliset里始终存放着全部数组元素。如果最大值是奇数,我们就可以停止了,因为最大值已经不能再减小了……
代码:
class Solution {public: int minimumDeviation(vector<int>& nums) { multiset<int> s; for (int x : nums) { s.insert((x & 1) ? (x << 1) : x); } int r = *s.rbegin() - *s.begin(); for (;;) { auto t = s.end(); const int x = *(--t); r = min(r, x - *s.begin()); if (x & 1) break; s.erase(t); s.insert(x >> 1); } return r; }};