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;i const 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}计算子集<