Number of pairs with constant difference and bitwi

2020-05-06 20:57发布

问题:

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=...=1l≤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 !");
        }   
    }
}