[LeetCode] 1675. Minimize Deviation in Array

You are given an array nums of n positive integers.

You can perform two types of operations on any element of the array any number of times:

  • If the element is even, divide it by 2.
    • For example, if the array is [1,2,3,4], then you can do this operation on the last element, and the array will be [1,2,3,2].
  • If the element is odd, multiply it by 2.
    • For example, if the array is [1,2,3,4], then you can do this operation on the first element, and the array will be [2,2,3,4].

The deviation of the array is the maximum difference between any two elements in the array.

Return the minimum deviation the array can have after performing some number of operations.

Example 1:

Input: nums = [1,2,3,4]
Output: 1
Explanation: You can transform the array to [1,2,3,2], then to [2,2,3,2], then the deviation will be 3 - 2 = 1.

Example 2:

Input: nums = [4,1,5,20,3]
Output: 3
Explanation: You can transform the array after two operations to [4,2,5,5,3], then the deviation will be 5 - 2 = 3.

Example 3:

Input: nums = [2,10,8]
Output: 3 

Constraints:

  • n == nums.length
  • 2 <= n <= 105
  • 1 <= nums[i] <= 109

数组的最小偏移量。

给你一个由 n 个正整数组成的数组 nums 。

你可以对数组的任意元素执行任意次数的两类操作:

如果元素是 偶数 ,除以 2
例如,如果数组是 [1,2,3,4] ,那么你可以对最后一个元素执行此操作,使其变成 [1,2,3,2]
如果元素是 奇数 ,乘上 2
例如,如果数组是 [1,2,3,4] ,那么你可以对第一个元素执行此操作,使其变成 [2,2,3,4]
数组的 偏移量 是数组中任意两个元素之间的 最大差值 。

返回数组在执行某些操作之后可以拥有的 最小偏移量 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimize-deviation-in-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这算是一道贪心的题目吧,思路不好想。

这道题有几个地方需要注意,首先,题目对于偏移量的定义其实是数组中最大的元素 - 最小的元素,我们的最终目的是要使得这个偏移量尽可能的小。同时注意题目允许的操作只有对偶数做除法和对奇数做乘法,所以如果想使得偏移量尽可能的小,我们应该让最大值尽可能地小,直到最大值是一个奇数为止,因为奇数是不能再做除法的。这里我们对 input 数组中的最小值不做任何变动,因为如果这个最小值是奇数的话,我们的确可以乘以 2,但是当我们下一轮再次扫描的时候,这个偶数又会被除以 2 变成奇数,这就是一个死循环了。所以大体思路是尽量把大的数字通过除以2的方式变小,来找最终那个最小的偏移量。

具体做法是首先将 input 数组中所有奇数乘以2,变成偶数,同时把所有数字都放入一个类似堆的数据结构里,这样可以做到自动排序。我这里的代码实现用的是 treeset。用 treeset 的原因是因为无需考虑重复的元素,只要能将所有 unique 的元素做到有序,方便我拿到最大的和最小的元素即可。将所有元素放入 treeset 之后,我去看一下 treeset 中的最大元素,如果他是偶数,那么我把他除以 2 再放回 treeset,如此循环往复直到 treeset 中最大的元素是奇数为止。此时 treeset 中最大元素 - 最小元素的差即是题目要找的最小的偏移量。

这道题的时间复杂度如下,因为数组中最大的数字有可能是 2 的倍数,所以对这个数字不断除以 2 的最大花费会到 logM,同时数组内可能所有元素都是偶数所以可能每个元素都需要做如此多的除以 2 的操作。如果数组的长度用 N 来表示的话,这一块的时间复杂度是 O(NlogM)。同时又因为每个元素在除以 2 之后会导致 treeset 的自动排序,所以又要乘以 logN。总体的复杂度是 O(NlogM * logN)

时间 O(NlogM * logN)

空间 O(n)

Java实现

 1 class Solution {
 2     public int minimumDeviation(int[] nums) {
 3         TreeSet<Integer> set = new TreeSet<>();
 4         for (int num : nums) {
 5             if (num % 2 == 1) {
 6                 set.add(num * 2);
 7             } else {
 8                 set.add(num);
 9             }
10         }
11 
12         int res = Integer.MAX_VALUE;
13         while (true) {
14             int top = set.last();
15             res = Math.min(res, top - set.first());
16             if (top % 2 == 0) {
17                 set.remove(top);
18                 set.add(top / 2);
19             } else {
20                 break;
21             }
22         }
23         return res;
24     }
25 }

 

LeetCode 题目总结

上一篇:斗地主随机发牌实现


下一篇:《Real-time Stereo Vision: Optimizing Semi-Global Matching》