Reputation: 8068
Inspired by an ambiguously asked question, I felt challenged to solve the harder interpretation of it, which is as following:
How to compute most efficiently all possible integer values (32 bit values) containing exactly n zeros (0 digits)? For example, given n = 7, the number of different integer values containing exactly 7 zeros is:
32*31*30*29*28*27*26 / (1*2*3*4*5*6*7) = 3.365.856
An example integer value with exactly 7 zeros would be:
11111111000000011111111111111111
In case you like to solve the problem by yourself, avoid to read my answer. Otherwise evaluate my answer, improve it or post an even better, more efficient one.
Upvotes: 1
Views: 244
Reputation: 8068
The idea of my algorithm is as following:
permut()
.The algorithm has two important characteristics:
Here the algorithm as Java code:
public static void main(String[] args) {
List<Integer> permutations = permut(7);
}
private static List<Integer> permut(int zeros) {
List<Integer> permutations = new ArrayList<>();
permut(zeros == 32 ? 0 : 0xFFFFFFFF << zeros, zeros, 31, permutations);
return permutations;
}
/*
* @param value
* for which to move the zero digit at bit position (zeros - 1)
* to the stopBit position
* @param zeros
* number of 0 digits available at the right most bit positions
* of value
* @param stopBit
* the left most bit position to move the zero digit at bit position
* (zeros - 1) to
* @param values
* to add the newly calculated integer values to
*/
private static void power(int value, int zeros, int stopBit, List<Integer> values) {
values.add(value);
if (zeros == 0) return;
int cleared = value | (1 << (zeros - 1));
for (int bit = zeros - 1; bit < stopBit;) {
power(cleared ^ (1 << ++bit), zeros - 1, bit - 1, values);
}
}
If you are curious if the algorithm behaves correctly, try the following checking methods with the modified main()
method:
public static void main(String[] args) {
int zeros = 7;
List<Integer> permutations = permut(zeros);
System.out.println("Expected number of values: " + combinations(zeros));
System.out.println("Returned number of values: " + permutations.size());
System.out.println("Returned values are unique: " + (new HashSet<>(permutations).size() == permutations.size()));
System.out.printf("All values contain %d zeros: %s\n", zeros, haveZeros(zeros, permutations));
}
private static long combinations(int zeros) {
long p = 1;
long q = 1;
for (int count = 0; count < zeros;) {
p *= (32 - count);
q *= (++count);
}
return p / q;
}
private static boolean haveZeros(int zeros, List<Integer> values) {
for (Integer value : values) {
int count = 0;
for (int bit = 1; bit != 0; bit = bit << 1) {
if ((value & bit) == 0) count++;
}
if (count != zeros) {
System.out.println(Integer.toBinaryString(value));
return false;
}
}
return true;
}
Upvotes: 1
Reputation: 2188
Assuming that you want to enumerate the actual numbers, you can simply create an array of chars of size 32 with exactly n 0, then permute the array
import java.io.*;
import java.util.*;
public class Solution
{
static char [] arr;
public static void main(String[]args)
{
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
arr = new char[5];
for(int i = 0; i < arr.length; i++)
{
if(n > 0)
{
arr[i] = '0';
n--;
}
else
arr[i] = '1';
}
permute(0);
}
public static void permute(int i)
{
if(i >= arr.length)
{
System.out.println(arr);
return;
}
int [] dups = new int[2];
for(int j = i; j < arr.length; j++)
{
if(dups[arr[j]-'0'] == 1)
continue;
dups[arr[j]-'0'] = 1;
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
permute(i+1);
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
It's slow because there are m! permutations where m is the size of the array. I set the size to be 5 to speed things up.
Upvotes: 0