Skip to content

Latest commit

 

History

History

1675

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

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 <= 5 * 104
  • 1 <= nums[i] <= 109

Companies: Samsung

Related Topics:
Array, Greedy, Heap (Priority Queue), Ordered Set

Hints:

  • Assume you start with the minimum possible value for each number so you can only multiply a number by 2 till it reaches its maximum possible value.
  • If there is a better solution than the current one, then it must have either its maximum value less than the current maximum value, or the minimum value larger than the current minimum value.
  • Since that we only increase numbers (multiply them by 2), we cannot decrease the current maximum value, so we must multiply the current minimum number by 2.

Solution 1. Reuse solution to 632

For each A[i], there is a limited number of transformed numbers.

Take [1,2,3,4] for example,

1 -> [1, 2]
2 -> [1, 2]
3 -> [3, 6]
4 -> [1, 2, 4]

And the problem can be transformed as follows:

For each A[i], pick a transformed number. In this way we will get a group of N numbers. Find a group what can minimize the maximum difference of the group.

This is exactly 632. Smallest Range Covering Elements from K Lists (Hard).

Time complexity

Generating the transformed array B takes O(NlogC) time where C is the maximum number in A.

The solution to 632 takes O(NK * logN) where K is the maximum length of B[i], i.e. logC.

So overall the time complexity is O(NlogN * logC).

// OJ: https://leetcode.com/problems/minimize-deviation-in-array/
// Author: github.com/lzl124631x
// Time: O(NlogN * logC) where C is the maximum number in A
// Space: O(NlogC)
class Solution {
public:
    int minimumDeviation(vector<int>& A) {
        int N = A.size();
        vector<vector<int>> B(N);
        for (int i = 0; i < N; ++i) {
            int x = A[i];
            B[i].push_back(x);
            if (x % 2 == 0) {
                while (x % 2 == 0) {
                    B[i].push_back(x / 2);
                    x /= 2;
                }
                reverse(begin(B[i]), end(B[i]));
            } else B[i].push_back(2 * x);
        }
        int mx = INT_MIN, ans = INT_MAX;
        vector<int> next(N);
        auto cmp = [&](int a, int b) { return B[a][next[a]] > B[b][next[b]]; };
        priority_queue<int, vector<int>, decltype(cmp)> pq(cmp);
        for (int i = 0; i < N; ++i) {
            pq.push(i);
            mx = max(mx, B[i][0]);
        }
        while (true) {
            int i = pq.top();
            pq.pop();
            ans = min(ans, mx - B[i][next[i]]);
            if (++next[i] == B[i].size()) break;
            mx = max(mx, B[i][next[i]]);
            pq.push(i);
        }
        return ans;
    }
};

Solution 2.

Instead of storing all the transformed values, we just need to store the lower bound and upper bound of the transformed values.

For a even number n, we divide it by 2 until it becomes a odd number, say k, so the lower and upper bounds are k, n, respectively.

For an odd number n, the lower and upper bounds are n and 2n respectively.

We push these ranges into a min heap pq. Now we can ignore the parity of the numbers in the min heap, we just need to uniformly increase the lower bound numbers towards the upper bound.

We use a mx to store the maximum value of all the lower bound values in the min heap.

Each time we pop a range with minimal lower bound. The current range of all the lower bounds in the min heap including the one just popped is mx - pq.top().first.

We multiply the lower bound by 2, and update the mx value and push the new lower bound with its upper bound back into the pq.

We stop until 2 * lower_bound exceeds upper bound.

Time complexity

We initialize the min heap by pushing N times, so it takes O(NlogN) time.

Each value in the min heap at most increases O(logC) times where C is the maximum value in A. So in the worst case we need to increase O(NlogC) times. Each time we need to push/pop into/from a min heap of size N which takes O(logN).

So overall the time complexity is O(NlogN * logC).

// OJ: https://leetcode.com/problems/minimize-deviation-in-array/
// Author: github.com/lzl124631x
// Time: O(NlogN * logC)
// Space: O(N)
// Ref: https://leetcode.com/problems/minimize-deviation-in-array/discuss/952819/Python-Priority-queue-and-record-the-lower-and-upper-bound
class Solution {
public:
    int minimumDeviation(vector<int>& A) {
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
        int mx = INT_MIN;
        for (int n : A) {
            if (n % 2 == 0) {
                int upper = n;
                while (n % 2 == 0) n /= 2;
                pq.emplace(n, upper);
            } else pq.emplace(n, 2 * n);
            mx = max(mx, n);
        }
        int ans = INT_MAX;
        while (true) {
            auto [val, upper] = pq.top();
            pq.pop();
            ans = min(ans, mx - val);
            mx = max(mx, 2 * val);
            if (2 * val > upper) break;
            pq.emplace(2 * val, upper);
        }
        return ans;
    }
};

Solution 3.

Solution 2 is increasing the number. But if we turn odd numbers n to 2n and decrease the numbers, we don't need to care about the lower bound because the lower bound is always met when the number becomes odd.

// OJ: https://leetcode.com/problems/minimize-deviation-in-array/
// Author: github.com/lzl124631x
// Time: O(NlogN * logC)
// Space: O(N)
class Solution {
public:
    int minimumDeviation(vector<int>& A) {
        int N = A.size(), ans = INT_MAX, mn = INT_MAX; // `mn` is the minimum number within the max heap
        priority_queue<int> pq;
        for (int n : A) {
            if (n % 2) n *= 2;
            pq.push(n);
            mn = min(mn, n);
        }
        while (true) {
            int mx = pq.top();
            pq.pop();
            ans = min(ans, mx - mn);
            if (mx % 2) break;
            mx /= 2;
            mn = min(mn, mx);
            pq.push(mx);
        }
        return ans;
    }
};