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:
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:
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 the 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 are 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 :
 

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

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to make atleast
// K elements of the given array
// equal by dividing by 2
import java.util.*;
class GFG{
 
// Function to return the
// minimum number of divisions
// required
static int get_min_opration(int arr[],
                            int N, int K)
{
  Vector<Integer> []vals = new Vector[200001];
   
  for (int i = 0; i < vals.length; i++)
    vals[i] = new Vector<Integer>();
   
  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].add(cur);
      x /= 2;
      ++cur;
    }
  }
 
  int ans = Integer.MAX_VALUE;
   
  for (int i = 0; i <= 200000; ++i)
  {
    // To obtain minimum
    // number of operations
    Collections.sort(vals[i]);
  }
   
  for (int i = 0; i <= 200000; ++i)
  {
    // If it is not possible
    // to make at least K
    // elements equal to vals[i]
    if ((vals[i].size()) < K)
      continue;
     
    // Store the number
    // of operations
    int sum = 0;
     
    for (int j = 0; j < K; j++)
    {
      sum += vals[i].get(j);
    }
     
    // Update the minimum
    // number of operations
    // required
    ans = Math.min(ans, sum);
  }
 
  return ans;
}
   
// Driver code
public static void main(String[] args)
{
  int N = 5, K = 3;
  int arr[] = {1, 2, 2, 4, 5};
  System.out.print(get_min_opration(arr, N, K));
}
}
 
// This code is contributed by shikhasingrajput
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to make atleast
# K elements of the given array
# equal by dividing by 2
import sys
 
# Function to return the
# minimum number of divisions
# required
def get_min_opration(arr, N, K):
     
    vals = [[] for _ in range(200001)]
    for i in range(N):
        x = arr[i]
 
        cur = 0
        while (x > 0):
             
            # cur: number of times a[i]
            # is divided by 2 to obtain x
            vals[x].append(cur)
            x //= 2
            cur += 1
 
    ans = sys.maxsize
    for i in range(200001):
         
        # To obtain minimum
        # number of operations
        vals[i] = sorted(vals[i])
 
    for i in range(200001):
 
        # If it is not possible
        # to make at least K
        # elements equal to vals[i]
        if (int(len(vals[i])) < K):
            continue
             
        # Store the number
        # of operations
        sum = 0
        for j in range(K):
            sum += vals[i][j]
             
        # Update the minimum
        # number of operations
        # required
        ans = min(ans, sum)
 
    return ans
 
# Driver code
if __name__ == '__main__':
     
    N = 5
    K = 3
    arr = [ 1, 2, 2, 4, 5 ]
     
    print(get_min_opration(arr, N, K))
 
# This code is contributed by mohit kumar 29
chevron_right

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
using System;
using System.Collections.Generic;
class GFG{
 
// Function to return the
// minimum number of divisions
// required
static int get_min_opration(int []arr,
                            int N, int K)
{
  List<int> []vals =
              new List<int>[200001];
   
  for (int i = 0; i < vals.Length; i++)
    vals[i] = new List<int>();
   
  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].Add(cur);
      x /= 2;
      ++cur;
    }
  }
 
  int ans = int.MaxValue;
   
  for (int i = 0; i <= 200000; ++i)
  {
    // If it is not possible
    // to make at least K
    // elements equal to vals[i]
    if ((vals[i].Count) < 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 = Math.Min(ans, sum);
  }
 
  return ans;
}
   
// Driver code
public static void Main(String[] args)
{
  int N = 5, K = 3;
  int []arr = {1, 2, 2, 4, 5};
  Console.Write(get_min_opration(arr, N, K));
}
}
 
// This code is contributed by shikhasingrajput
chevron_right

Output: 
1





 

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




Recommended Posts:


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.



Article Tags :
Practice Tags :