How to find the number of pairs whose difference is a given constant and their bitwise AND is zero? Basically, all (x,y) such that x-y = k; where k is a given constant and x&y = 0;
问题:
回答1:
An interesting problem.
Let kn-1...k1k0 be the the binary representation of k.
Let l be the index of the smallest i such that ki=1
We can remark that a potential pair of solutions x and y must have all their bits i, i<l at zero.
Otherwise the only way to have a difference x-y with its ith bit unset would be to have xi=yi=1 and x&y will not have its ith bit unset.
Now we arrive at the first bit at one at index l.
The situation is more complex, as we have several ways to have this bit set in the result of x-y.
For that we must consider the set of bits l..m such that ki=ki+1=ki+2=...=1 ∀l≤i<m and km=0
For instance, if l=0 and m=1, the two LSB of k are 01 and we can get this result by computing either 01-00 (1-0) or 10-01 (2-1). In either case, the result is correct (1) and the bits of x and y are opposite and give a zero when anded.
When the sequence is composed of several ones, the replacement must done from LSB for every pair of consecutive ones.
Here is an example. To simplify, we assume that the sequence starts at bit 0, but the generalization is immediate :
k=0111
Trivial solution x=k=0111 y=0=0000
Rewrite 1 at LSB as 2-1: add 1 to x and 1 to y
x=0111+0001=1000=8 y=0000+0001=0001
Rewrite bit at 1 at index 1 (21) as 4-2: add 2 to x and add 2 to y
x=0111+0010=1011 y=0000+0010=0010
Rewrite bit at 1 at index 2 (22) as 4=8-4: add 4 to x and add 4 to y
x=0111+0100=1011 y=0000+0100=0100
So, for a sequence of ones followed by a zero :
Compute the trivial solution where x=<sequence> and y=0
for every one in the sequence
let i be the position of this one
generate a new solution by adding 2^i to x and y of the trivial solution
To resume one must decompose the number in two kind of sequences, starting at LSB
* zeroes is a sequence of consecutive zeroes
* ones is a sequence of ones followed by a zero
The results are obtained by replacing
* zeroes by a set of zeroes
* ones by adding 0, 1, 2, 4, 2i to the trivial solution 01111..11/000...000
Example :
k = 22 = 16+4+2 = 0 0 0 1 0 1 1 0
Rewrite first sequence
011 -> 011/000 (trivial solution)
100/001 (trivial solution+1)
101/010 (trivial solution+2)
Rewrite second sequence
01 -> 01/00 (trivial solution)
10/01 (trivial solution + 1)
And so there are 3*2=6 solutions
010110/000000 22/0
011000/000010 24/2
011010/000100 26/4
100110/010000 38/16
101000/010010 40/18
101010/010100 42/20
回答2:
Java implementation would be like this ...
import java.util.ArrayList;
public class FindPairs {
public static void main(String args[]) {
int arr[] = {1,3,4,5,6,9};
int k = 3;
ArrayList<String> out = new ArrayList<String>();
for(int i=0; i<arr.length; i++) {
for(int j=i+1; j<arr.length; j++) {
if((Math.abs(arr[i]-arr[j]) == k) && ((arr[i]&arr[j]) == 0)) {
out.add("("+arr[i]+","+arr[j]+")");
}
}
}
if(out.size()>0) {
for(String pair:out) {
System.out.println(pair);
}
}else {
System.out.println("No such pair !");
}
}
}