Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 计算数组中按位“0”的无序对数;及;是O(n)或O(n*log(n))中的2的幂_Algorithm_Data Structures_Bit Manipulation_Bitmask - Fatal编程技术网

Algorithm 计算数组中按位“0”的无序对数;及;是O(n)或O(n*log(n))中的2的幂

Algorithm 计算数组中按位“0”的无序对数;及;是O(n)或O(n*log(n))中的2的幂,algorithm,data-structures,bit-manipulation,bitmask,Algorithm,Data Structures,Bit Manipulation,Bitmask,如何计算数组中按位和为2的幂的无序对数。例如,如果数组是[10,7,2,8,3]。答案是6。 说明(基于0的索引): a[0]&a[1]=2 a[0]&a[2]=2 a[0]&a[3]=8 a[0]&a[4]=2 a[1]&a[2]=2 a[2]&a[4]=2 我想到的唯一办法就是暴力。如何优化它以在O(n)或O(n*log(n))中执行 对数组大小的限制最大为10^5。该数组中的值最多可为10^12 这是我试过的暴力代码 intans=0; for(int i=0;i

如何计算数组中按位
2的幂的无序对数。例如,如果数组是
[10,7,2,8,3]
。答案是
6
。 说明(基于0的索引):

  • a[0]&a[1]=2
  • a[0]&a[2]=2
  • a[0]&a[3]=8
  • a[0]&a[4]=2
  • a[1]&a[2]=2
  • a[2]&a[4]=2
我想到的唯一办法就是暴力。如何优化它以在O(n)O(n*log(n))中执行

对数组大小的限制最大为
10^5
。该数组中的值最多可为
10^12

这是我试过的暴力代码

intans=0;
for(int i=0;i
将值数组转换为索引集数组,其中每个索引集对应于特定位,并包含具有该位集的原始集合中的值的索引。例如,示例数组A=
[10,7,2,8,3]
变成B=
[{1,4}、{0,1,2,4}、{1}、{0,3}]
。固定大小的位向量数组是实现这一点的理想数据结构,因为它使集合并集/交集/集合减号相对容易且高效

一旦你有了集合B的数组(需要O(nm)时间,
m
是整数的大小,以位为单位),再次迭代A的每个元素i,计算∑j|Bj∖i&set减号&大杯子;kBk:k≠J∧i∈Bk |:i∈北京。把这些加在一起,除以2,这应该是对的数量(“除以2”是因为它计算每对两次,因为它计算的是每对数字的数量)。应该只取O(nm2),假设将set减号运算计算为O(1)——如果将它们计算为O(n),则返回到O(n2),但如果有有效的位集,则至少常数因子应该很小

伪代码:

foreach A[i] in A:
    foreach bit in A[i]:
        B[bit] += {i}

pairs = 0
foreach A[i] in A:
    foreach B[j] in B:
        if i in B[j]:
            tmp = B[j] - {i}
            foreach B[k] in B:
                if k != j && i in B[k]:
                    tmp -= B[k]
            pairs += |tmp|

return pairs/2

虽然这个答案适用于较小的范围约束(可能适合2^20左右),但我认为我应该添加它,因为它可能会添加一些有用的信息

我们可以调整,使其具有
O(2^N*N^2+N*N)
复杂性的解决方案,其中
N
是范围内的位数,
N
是列表中的元素数。(因此,如果整数被限制为[11048576]或2^20,且
n
为100000,则我们的迭代次数为2^20*20^2+100000*20=421430400次。)

我们的想法是,我们想要计算具有重叠比特子集的实例,并添加一个固定的集合比特。给定
Ai
——为了简单起见,取
6=b110
——如果我们要找到所有的伙伴,并且为零,我们将取
Ai
的否定

110 -> ~110 -> 001
现在,我们可以构建一个动态程序,该程序采用递减蒙版,从整数开始,向左递减蒙版

001
^^^

001
^^

001
^
Ai
反运算中的每个设定位代表一个零,可以与1或0进行AND运算,以达到相同的效果。
Ai
反运算中的每个未设置位表示
Ai
中的一个设定位,我们只想将其与零配对,但单个设定位除外

我们通过分别检查每个可能性来构造这个集合位。因此,在哪里计算那些将和
Ai
为零的配对,我们可以做如下的事情

001 ->
  001
  000
我们现在要列举

011 ->
  011
  010

101 ->
  101
  100
每次修复一个位

我们可以通过向内部迭代添加维度来实现这一点。当掩码的末尾确实有一个设置位时,我们通过只计算将设置位的前一个DP单元的结果来“修复”相关位,而不是通常的子集的并集,这些子集可以设置位或不设置位

下面是一些JavaScript代码,与蛮力解决方案进行对比,并在最后进行测试

var调试=0;
函数bruteForce(a){
让答案=0;
for(设i=0;iconst dp=新数组(1假设有m个值不是2的幂。然后有m*(m+1)/2个无序的值对,当和在一起时不是2的幂。@ChrisHall 6和3不是2的幂。根据你的陈述,有2*3/2=3个无序的值对,当和在一起时不是2的幂。但是对于输入,[6,3],有零对这样的无序配对,一对当和在一起时是2的幂。你能澄清一下吗?@啊,大脑衰退..2的幂不是2的倍数:-(很抱歉。好的。我们正在寻找无序对,它们正好有一个共同点。需要更多的思考。
a
中的值的界限是什么?因为可能有O(n2)这样的无序对,很难在更短的时间内生成它们,但如果你只想计算存在的数量,这是可能的。对不起,我不理解你的数学符号。你能用一个例子来说明,正如你在句子第一部分解释的,基本上显示所有加在一起除以2的内容吗?好的,所以我ink我修复了它,并添加了伪代码来说明algorithm@ChrisDodd:
B
中的每个集合的大小可以与
n
成比例。通过
B[j]-{i}计算子集<