Open In App

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 :
 




// 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;
}




// 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




# 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




// 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




<script>
 
      // JavaScript program to make atleast
      // K elements of the given array
      // equal by dividing by 2
       
      // Function to return the
      // minimum number of divisions
      // required
      function get_min_opration(arr, N, K) {
        var vals = new Array(200001);
 
        for (var i = 0; i < vals.length; i++) vals[i] = [];
 
        for (var i = 0; i < N; ++i) {
          var x = arr[i];
          var cur = 0;
 
          while (x > 0) {
            // cur: number of
            // times a[i] is
            // divided by 2
            // to obtain x
            vals[x].push(cur);
            x = parseInt(x / 2);
            ++cur;
          }
        }
 
        //Max integer value
        var ans = 2147483648;
 
        for (var i = 0; i <= 200000; ++i) {
          // If it is not possible
          // to make at least K
          // elements equal to vals[i]
          if (vals[i].length < K) continue;
 
          // Store the number
          // of operations
          var sum = 0;
 
          for (var 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
      var N = 5,
        K = 3;
      var arr = [1, 2, 2, 4, 5];
      document.write(get_min_opration(arr, N, K));
       
</script>

Output: 
1

 

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


Article Tags :