Find K such that sum of hamming distances between K and each Array element is minimised
Given an array arr[] of N non-negative integers and an integer P (1 ≤ P ≤ 30), which denotes the upper limit of any number in the array to be (2P – 1). The task is to find a number such that the sum of Hamming distances between the number itself and all the numbers in the array is minimum. If there are multiple answers possible print any one of them.
Note: Hamming distance between two numbers is the number of positions in their binary representation in which the bits of the numbers are different
Examples:
Input: N = 4, P = 4
arr[] = {12, 11, 8, 10}
Output: 8
Explanation: The number 8 has minimum sum of hamming distances.
Hamming distance from 12: 1
Hamming distance from 11: 2
Hamming distance from 8: 0
Hamming distance from 10: 1
10 can also be a valid answer.Input: N = 3, P = 3
arr[] = {5, 2, 7}
Output: 7
Approach: This problem can be solved using Greedy approach and bits manipulation. With observation, it can be said that In the final answer, only those bits will be set which have higher number of 1s for all array elements compared to 0s. Because otherwise, the total sum of different bits will increase. Follow the steps mentioned below to solve the problem:
- Create a 2D array bits[][] to keep count of bits for all numbers at each of the P bit positions.
- Start iterating the array from the start.
- For each array element increase the count of bit for each set bit in the bits[][] array.
- After iteration is over check the total number of set bits in the bits array.
- If the number of set bits in a position is greater than the number of 0s in that bit position set that bit in resultant number as 1, otherwise as 0.
- Return the final number as result.
Illustration:
For example take the array, arr[] = {12, 11, 8, 10} and P = 4.
Now see the bit representation of the numbers in the following image:Logical Representation
From the above image it can be clearly seen that the least significant bit has more number of 0s compared to 1s.
Similarly 3rd bit and the most significant bit have more number of 0s and 1s respectively.
But the 2nd bit has same number of 0s and 1s.
So the resultant number can have binary representation 1010 or 1000 i.e. it can be 10 or 8.
Below is the implementation of the above approach.
C++
// C++ code to find a number y such that // sum of hamming distance between y // and all the numbers given in array // is minimum #include <bits/stdc++.h> using namespace std; // Function to find the number int findNum( int arr[], int P, int N) { // Creating the bits 2D array int bits[N + 1][P + 1]; // Setting each column as 0 in row 0 // to ensure proper // addition for all i upto n for ( int i = 0; i < P; i++) bits[0][i + 1] = 0; // Filling the bits array for ( int i = 0; i < N; i++) { int j = 1; // For each bit from 1 to P for ( int k = 1; k <= P; k++) { int temp = arr[i]; int x = 0; // If kth bit is set in temp // set x = 1 else x as 0 if (temp & j) x = 1; // If kth bit is set // add x = 1 to previous value // in the same column bits[i + 1][k] = bits[i][k] + x; // Left shift j to check next bit j = j << 1; } } // x here is the bit contribution // in decimal int x = 1; // Declare variable to store answer int y = 0; // For each bit in the last row // check the count of 1s. for ( int i = 1; i <= P; i++) { // If numbers of 1s is greater than // number of 0s then add // that bit's contribution to y // else do not add anything if (bits[N][i] > N / 2) y += x; // multiply x by 2 each time to get // the new bit value as at bit 0 // value is 2^0 at bit 1 it // is 2^1, at bit 2 is 2^2 and so on x *= 2; } return y; } // Driver code int main() { int N = 4, P = 4; // Declaring the array int arr[N] = { 12, 11, 8, 10 }; int ans = findNum(arr, P, N); cout << ans; return 0; } |
Java
// Java code to find a number y such that // sum of hamming distance between y // and all the numbers given in array // is minimum class GFG { // Function to find the number static int findNum( int [] arr, int P, int N) { // Creating the bits 2D array int [][] bits = new int [N + 1 ][P + 1 ]; // Setting each column as 0 in row 0 // to ensure proper // addition for all i upto n for ( int i = 0 ; i < P; i++) bits[ 0 ][i + 1 ] = 0 ; // Filling the bits array for ( int i = 0 ; i < N; i++) { int j = 1 ; // For each bit from 1 to P for ( int k = 1 ; k <= P; k++) { int temp = arr[i]; int x = 0 ; // If kth bit is set in temp // set x = 1 else x as 0 if ((temp & j) != 0 ) x = 1 ; // If kth bit is set // add x = 1 to previous value // in the same column bits[i + 1 ][k] = bits[i][k] + x; // Left shift j to check next bit j = j << 1 ; } } // x1 here is the bit contribution // in decimal int x1 = 1 ; // Declare variable to store answer int y = 0 ; // For each bit in the last row // check the count of 1s. for ( int i = 1 ; i <= P; i++) { // If numbers of 1s is greater than // number of 0s then add // that bit's contribution to y // else do not add anything if (bits[N][i] > N / 2 ) y += x1; // multiply x by 2 each time to get // the new bit value as at bit 0 // value is 2^0 at bit 1 it // is 2^1, at bit 2 is 2^2 and so on x1 *= 2 ; } return y; } // Driver code public static void main(String args[]) { int N = 4 , P = 4 ; // Declaring the array int [] arr = { 12 , 11 , 8 , 10 }; int ans = findNum(arr, P, N); System.out.println(ans); } } // This code is contributed by gfgking |
Python3
# Python program to implement # the above approach # Function to find the number def findNum(arr, P, N) : # Creating the bits 2D array bits = [[ 0 ] * (N + 1 )] * (P + 1 ) # Setting each column as 0 in row 0 # to ensure proper # addition for all i upto n for i in range ( 0 , P) : bits[ 0 ][i + 1 ] = 0 # Filling the bits array for i in range (N) : j = 1 # For each bit from 1 to P for k in range ( 1 , P + 1 ) : temp = arr[i] x = 0 # If kth bit is set in temp # set x = 1 else x as 0 if (temp & j) : x = 1 # If kth bit is set # add x = 1 to previous value # in the same column bits[i + 1 ][k] = bits[i][k] + x # Left shift j to check next bit j = j << 1 # x here is the bit contribution # in decimal x = 1 # Declare variable to store answer y = 0 # For each bit in the last row # check the count of 1s. for i in range ( 1 , P + 1 ) : # If numbers of 1s is greater than # number of 0s then add # that bit's contribution to y # else do not add anything if (bits[N][i] > N / 2 ) : y + = x # multiply x by 2 each time to get # the new bit value as at bit 0 # value is 2^0 at bit 1 it # is 2^1, at bit 2 is 2^2 and so on x * = 2 return y # Driver code N = 4 P = 4 # Declaring the array arr = [ 12 , 11 , 8 , 10 ] ans = findNum(arr, P, N) print (ans) # This code is contributed by sanjoy_62. |
C#
// C# code to find a number y such that // sum of hamming distance between y // and all the numbers given in array // is minimum using System; class GFG { // Function to find the number static int findNum( int [] arr, int P, int N) { // Creating the bits 2D array int [, ] bits = new int [N + 1, P + 1]; // Setting each column as 0 in row 0 // to ensure proper // addition for all i upto n for ( int i = 0; i < P; i++) bits[0, i + 1] = 0; // Filling the bits array for ( int i = 0; i < N; i++) { int j = 1; // For each bit from 1 to P for ( int k = 1; k <= P; k++) { int temp = arr[i]; int x = 0; // If kth bit is set in temp // set x = 1 else x as 0 if ((temp & j) != 0) x = 1; // If kth bit is set // add x = 1 to previous value // in the same column bits[i + 1, k] = bits[i, k] + x; // Left shift j to check next bit j = j << 1; } } // x1 here is the bit contribution // in decimal int x1 = 1; // Declare variable to store answer int y = 0; // For each bit in the last row // check the count of 1s. for ( int i = 1; i <= P; i++) { // If numbers of 1s is greater than // number of 0s then add // that bit's contribution to y // else do not add anything if (bits[N, i] > N / 2) y += x1; // multiply x by 2 each time to get // the new bit value as at bit 0 // value is 2^0 at bit 1 it // is 2^1, at bit 2 is 2^2 and so on x1 *= 2; } return y; } // Driver code public static int Main() { int N = 4, P = 4; // Declaring the array int [] arr = new int [4] { 12, 11, 8, 10 }; int ans = findNum(arr, P, N); Console.Write(ans); return 0; } } // This code is contributed by Taranpreet |
Javascript
<script> // JavaScript code for the above approach // Function to find the number function findNum(arr, P, N) { // Creating the bits 2D array let bits = new Array(N + 1); for (let i = 0; i < N + 1; i++) { bits[i] = new Array(P + 1); } // Setting each column as 0 in row 0 // to ensure proper // addition for all i upto n for (let i = 0; i < P; i++) bits[0][i + 1] = 0; // Filling the bits array for (let i = 0; i < N; i++) { let j = 1; // For each bit from 1 to P for (let k = 1; k <= P; k++) { let temp = arr[i]; let x = 0; // If kth bit is set in temp // set x = 1 else x as 0 if (temp & j) x = 1; // If kth bit is set // add x = 1 to previous value // in the same column bits[i + 1][k] = bits[i][k] + x; // Left shift j to check next bit j = j << 1; } } // x here is the bit contribution // in decimal let x = 1; // Declare variable to store answer let y = 0; // For each bit in the last row // check the count of 1s. for (let i = 1; i <= P; i++) { // If numbers of 1s is greater than // number of 0s then add // that bit's contribution to y // else do not add anything if (bits[N][i] > Math.floor(N / 2)) y += x; // multiply x by 2 each time to get // the new bit value as at bit 0 // value is 2^0 at bit 1 it // is 2^1, at bit 2 is 2^2 and so on x *= 2; } return y; } // Driver code let N = 4, P = 4; // Declaring the array let arr = [12, 11, 8, 10]; let ans = findNum(arr, P, N); document.write(ans); // This code is contributed by Potta Lokesh </script> |
8
Time Complexity: O(N * P)
Auxiliary Space: O(N * P)
Please Login to comment...