Count of Array elements to be divided by 2 to make at least K elements equal

Given an integer array arr[] of size N, the task is to find the minimum number of array elements required to be divided by 2, to make at least K elements in the array equal.

Example :

Input: arr[] = {1, 2, 2, 4, 5}, N = 5, K = 3
Output: 1
Explanation:
Dividing 4 by 2 modifies the array to {1, 2, 2, 2, 5} with 3 equal elements.

Input: arr[] = {1, 2, 3, 4, 5}, N = 5, K = 3
Output: 1
Explanation:
Dividing 2 and 3 by 2 modifies the array to {1, 1, 1, 4, 5} with 3 equal elements.

Approach:
Every integer X can be divided by 2 log2(X) times to get a non-zero value. Hence, we need to perform these log2(arr[i]) operations on every array element arr[i] and for every value obtained after a division, store the number of operations required to reach the respective value. Once, all operations are performed for all array elements, for every value that at least K array elements have been reduced to at some point, find the sum of smallest K operations required among all of them. Find the minimum number of operations required among all such instances.



Illustration:
arr[] = {1, 2, 2, 4, 5}, N = 5, K = 3

Only 1 element can have a value 5, so ignore.
Only 1 element can have a value 4, so ignore.
No element can have a value 3.

4 elements can have a value 2.
{1, 2, 2, (4/2), (5/2) } -> {1, 2, 2, 2, 2}
Since, the number of possibilities exceeds K, find the sum of the smallest K operations.
arr[1] -> 0 operations
arr[2] -> 0 operations
arr[3] -> 1 operation
arr[4] -> 1 operation
Hence, sum of smallest 3 operations = (0 + 0 + 1) = 1

All 5 elements can be reduced to 1.
{1, 2/2, 2/2, (4/2)/2, (5/2)/2} -> {1, 1, 1, 1, 1}
Hence, the sum of smallest 3 operations = (0 + 1 + 1) = 2

Hence, the minimum number of operations required to make at least K elements equal is 1.

Follow the steps below to solve the problem using the above approach:

  1. Create a matrix vals[][] such that vals [ X ][ j ] will store the number of operations needed to obtain value X from an array element.
  2. Traverse the array and for every array element:
    • Initialize x = arr[i]. Initialize count of operations cur as 0.
    • At every step, update x = x/2 and increment cur by 1. Insert cur into vals[x] as the number of divisions required to obtain current value of x.
  3. Now, all possible values that can be obtained by repetitive division of every arr[i] by 2 with the number of such divisions required to get that value is stored in the vals[][] matrix.
  4. Now, traverse the matrix vals[][] and for every row, perform the following:
    • Check if the current row vals[i] consists of at least K elements or not. If vals[i] < K, ignore as at least K array elements cannot be reduced to i.
    • If vals[i].size() is ≥ K, calculate the sum of the row i. Update ans = min(ans, sum of vals[i]).
  5. The final value of ans gives us the desired answer.

Below is the implementation of the above approach :

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to make atleast
// K elements of the given array
// equal by dividing by 2
  
#include <bits/stdc++.h>
using namespace std;
  
// Function to return the
// minimum number of divisions
// required
int get_min_opration(int arr[], int N,
                     int K)
{
    vector<vector<int> > vals(200001);
    for (int i = 0; i < N; ++i) {
        int x = arr[i];
  
        int cur = 0;
        while (x > 0) {
            // cur: number of
            // times a[i] is
            // divided by 2
            // to obtain x
            vals[x].push_back(cur);
            x /= 2;
            ++cur;
        }
    }
  
    int ans = INT_MAX;
    for (int i = 0; i <= 200000; ++i) {
        // To obtain minimum
        // number of operations
        sort(vals[i].begin(),
             vals[i].end());
    }
    for (int i = 0; i <= 200000; ++i) {
  
        // If it is not possible
        // to make at least K
        // elements equal to vals[i]
        if (int(vals[i].size()) < K)
            continue;
        // Store the number
        // of operations
        int sum = 0;
        for (int j = 0; j < K; j++) {
            sum += vals[i][j];
        }
        // Update the minimum
        // number of operations
        // required
        ans = min(ans, sum);
    }
  
    return ans;
}
// Driver Program
int main()
{
    int N = 5, K = 3;
  
    int arr[] = { 1, 2, 2, 4, 5 };
    cout << get_min_opration(arr, N, K);
  
    return 0;
}

chevron_right


Output:

1

Time Complexity: O (N * log N)
Auxiliary Space: O (N * log N)

competitive-programming-img




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.