查找按位且为0的数组中的所有数字对

时间:2015-09-05 17:33:11

标签: algorithm bitwise-and

我最近遇到了一个问题,它是关于计算数组中所有数字对的位数和位数。所需的复杂度为O(n)或O(nlog(n))或更小。数字在1到1000000之间。

我的方法是以二进制形式写入每个数字,然后检查数字的每个位,检查它是0还是1,如果位为1,我可以将那些在同一位置具有0的数字,如果位为0,可以取任何数字为0 *(任意数字)= 0.但我的时间复杂度为O(n ^ 2),不会通过。

3 个答案:

答案 0 :(得分:2)

我将从给定数组构建一个二进制树,以便每个位定义我们是在树中向左还是向右。对于三位数101,它将是:

NODE - > (1)右 - > (0)左 - > (1)对

(我不知道如何在这里格式化二进制尝试,它会删除所有多个空格,所以我很抱歉这样糟糕的插图)

所以这需要O(n)(构建分支并创建新节点是O(1))。

然后使用递归方法从数组中取一个数字(X),处理其位并在树上行走,以便每个位IF (k == num_of_bits) Then print pair (X, current node value) Return IF (left branch exists) Then take left branch with X[num_of_bits..k+1] // we go left anyway //ELSE - 'else' here was a mistake IF X[k] == 0 // if the bit is 0 we can go in both directions Then IF (right branch exists) Then take right branch with X[num_of_bits..k+1]

{{1}}

现在计算复杂性有点棘手,因为最坏的情况似乎是所有位都是0但是在树中你将只有一个分支...... 它看起来我的复杂性是O(n * log(n)) - 如果我没有忽略任何东西。

因此总共是O(n)+ O(n * log(n))=>为O(n *的log(n))

答案 1 :(得分:1)

您可以使用尝试的概念来解决此问题。

插入trie:首先,在trie树中插入所有数字。这棵树将是一棵二叉树,我们将左边的子节点视为0,将右边的子节点视为1.如果要插入具有二进制表示001的1,则它将如下所示:

  

根 - >左(0) - >左(0) - >右(1)

如果路径已退出,请勿再次添加新节点。在这种情况下,只遍历树并添加0 0r 1,其中路径不存在。每个叶节点也将保持每个数字的计数。因此,插入的时间复杂度将为O(n * log2(max)),因为我们插入了n个元素,并且每次插入所花费的时间等于数组最大数量的位数。

在trie中查询:对于数组中的每个数字,比较数字n中的位值和您所做树的位数。从第一位数字开始。

  

如果该位为零,则遍历树的右侧或左侧,如果该位为1,   遍历树的左侧。

为数字的每一位执行此操作,直至到达第n位。如果你不能回头,那就不可能回来了。如果到达第n位,则返回叶节点中存储的计数。 有关更详细的说明,请参阅下面的链接,

Trie tree

答案 2 :(得分:0)

你可以这个暴力

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;

class BitAnd {

public static void main(String[] args) throws IOException {
    BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
//  Scanner sc= new Scanner(System.in);             
    int t=Integer.parseInt(br.readLine());
    while(t-->0){
        int n=Integer.parseInt(br.readLine());
        int arr[]= new int[n];

        String s[]=br.readLine().split(" ");
        for (int i = 0; i < s.length; i++) {
            arr[i]=Integer.parseInt(s[i]);              
        }
        int c=0;            
        for (int i = 0; i < arr.length; i++) {
            for (int j = i+1; j < arr.length; j++) {
                if((arr[i]&arr[j])==0)c++;                  
            }               
        }
        System.out.println(c*2);            
    }     
  }
}