同步操作将从 doocs/leetcode 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
给你一个由 n
个正整数组成的数组 nums
。
你可以对数组的任意元素执行任意次数的两类操作:
2
<ul>
<li>例如,如果数组是 <code>[1,2,3,4]</code> ,那么你可以对最后一个元素执行此操作,使其变成 <code>[1,2,3,<strong>2</strong>]</code></li>
</ul>
</li>
<li>如果元素是 <strong>奇数</strong> ,<strong>乘上</strong> <code>2</code>
<ul>
<li>例如,如果数组是 <code>[1,2,3,4]</code> ,那么你可以对第一个元素执行此操作,使其变成 <code>[<strong>2</strong>,2,3,4]</code></li>
</ul>
</li>
数组的 偏移量 是数组中任意两个元素之间的 最大差值 。
返回数组在执行某些操作之后可以拥有的 最小偏移量 。
示例 1:
输入:nums = [1,2,3,4] 输出:1 解释:你可以将数组转换为 [1,2,3,2],然后转换成 [2,2,3,2],偏移量是 3 - 2 = 1
示例 2:
输入:nums = [4,1,5,20,3] 输出:3 解释:两次操作后,你可以将数组转换为 [4,2,5,5,3],偏移量是 5 - 2 = 3
示例 3:
输入:nums = [2,10,8] 输出:3
提示:
n == nums.length
2 <= n <= 5 * 104
1 <= nums[i] <= 109
直观上,为了得到数组的最小偏移量,我们需要将减小数组的最大值,增大数组的最小值。
由于每次可以执行乘、除两种操作:将奇数乘以 $2$;将偶数除以 $2$,情况较为复杂,我们可以将奇数统一乘以 $2$,转成偶数,这样就等价于只有一种除法操作。除法操作只能减少某个数,而只有减少最大值,结果才可能更优。
因此,我们用优先队列(大根堆)维护数组的最大值,每次取出堆顶元素做除法操作,将新值放入堆中,并且更新最小值以及堆顶元素与最小值的差值的最小值。
当堆顶元素为奇数时,操作停止。
时间复杂度 $O(n\log n \times \log m)$。其中 $n$, $m$ 分别是数组 nums
的长度以及数组的最大元素。由于数组中的最大元素除以 $2$ 的操作最多有 $O(\log m)$ 次,因此全部元素除以 $2$ 的操作最多有 $O(n\log m)$ 次。每次弹出、放入堆的操作,时间复杂度为 $O(\log n)$。因此,总的时间复杂度为 $O(n\log n \times \log m)$。
class Solution:
def minimumDeviation(self, nums: List[int]) -> int:
h = []
mi = inf
for v in nums:
if v & 1:
v <<= 1
h.append(-v)
mi = min(mi, v)
heapify(h)
ans = -h[0] - mi
while h[0] % 2 == 0:
x = heappop(h) // 2
heappush(h, x)
mi = min(mi, -x)
ans = min(ans, -h[0] - mi)
return ans
class Solution {
public int minimumDeviation(int[] nums) {
PriorityQueue<Integer> q = new PriorityQueue<>((a, b) -> b - a);
int mi = Integer.MAX_VALUE;
for (int v : nums) {
if (v % 2 == 1) {
v <<= 1;
}
q.offer(v);
mi = Math.min(mi, v);
}
int ans = q.peek() - mi;
while (q.peek() % 2 == 0) {
int x = q.poll() / 2;
q.offer(x);
mi = Math.min(mi, x);
ans = Math.min(ans, q.peek() - mi);
}
return ans;
}
}
class Solution {
public:
int minimumDeviation(vector<int>& nums) {
int mi = INT_MAX;
priority_queue<int> pq;
for (int v : nums) {
if (v & 1) v <<= 1;
pq.push(v);
mi = min(mi, v);
}
int ans = pq.top() - mi;
while (pq.top() % 2 == 0) {
int x = pq.top() >> 1;
pq.pop();
pq.push(x);
mi = min(mi, x);
ans = min(ans, pq.top() - mi);
}
return ans;
}
};
func minimumDeviation(nums []int) int {
q := hp{}
mi := math.MaxInt32
for _, v := range nums {
if v%2 == 1 {
v <<= 1
}
heap.Push(&q, v)
mi = min(mi, v)
}
ans := q.IntSlice[0] - mi
for q.IntSlice[0]%2 == 0 {
x := heap.Pop(&q).(int) >> 1
heap.Push(&q, x)
mi = min(mi, x)
ans = min(ans, q.IntSlice[0]-mi)
}
return ans
}
type hp struct{ sort.IntSlice }
func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any {
a := h.IntSlice
v := a[len(a)-1]
h.IntSlice = a[:len(a)-1]
return v
}
func (h *hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] }
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。