我有一个数字数组,我想计算所有可能的对的组合,对于这些对,异或运算大于与运算。
示例:
4,3,5,2
可能的配对为:
(4,3) -> xor=7, and = 0
(4,5) -> xor=1, and = 4
(4,2) -> xor=6, and = 0
(3,5) -> xor=6, and = 1
(3,2) -> xor=1, and = 2
(5,2) -> xor=7, and = 0
Valid pairs for which xor > and are (4,3), (4,2), (3,5), (5,2) so result is 4.
这是我的程序:
def solve(array):
n = len(array)
ans = 0
for i in range(0, n):
p1 = array[i]
for j in range(i, n):
p2 = array[j]
if p1 ^ p2 > p1 & p2:
ans +=1
return ans
时间复杂度是O(n^2),但是我的数组大小是1到10^5,数组中的每个元素是1到2^30,那么如何降低这个程序的时间复杂度呢?
3条答案
按热度按时间q7solyqu1#
这使用了和你一样的算法,所以它仍然是O(n^2),但是你可以使用numpy来加速这个操作:
np.bitwise_xor
对两个数组执行按位异或运算np.bitwise_and
对两个数组执行按位与运算a ^ a == 0
,我们可以简单地将整个数组求和,然后将结果除以2得到答案。您还可以完全跳过numpy,在运行代码之前使用
numba
对您自己的代码进行JIT编译。最后,下面是我对Dave's algorithm的实现:
而且,作为一个数字兼容函数,我需要定义一个
get_msb
,因为numba.njit
不能处理内置的python函数比较运行时,我们看到numba方法明显比numpy方法快,后者本身比python中的循环快。
Dave给出的线性时间算法比numpy方法更快,当输入大于1000个元素时,它开始比numba编译的代码更快,numba编译版本的这种方法甚至更快--它在100个元素时就超过了numba编译的
loopy
。对于较大的输入,Dave算法的Kelly's excellent implementation与我的numba版本的实现相当
(Your实现被标记为“loopy”。图中的其他图例标记与我上面回答的函数名相同。Kelly的实现被标记为“kelly”)
c9x0cxw02#
Dave算法的另一种实现:
fykwrbwg3#
假设
a
和b
是整数,则a^b > a&b
当且仅当a
和b
具有不同的最高置位。解决方案:使用一个计数Map,其中键是最高的设置位。在线性时间内填充。
然后,处理键,假设总共有n个整数,某个键有r个整数(具有相同的最高设置位),然后该键将r (n-r)加到xor〉and的对的计数上,也就是说,r个整数中的每一个都可以与具有不同最高设置位的(n-r)中的每一个配对。
这会对所有内容进行双重计数,因此在最后除以2。
示例:
假设我们有8个整数,其中3个的第三位是最高置位,3个是第四位,2个是第五位。
因此,根据我的算法,我们有三个大小分别为3、3和2的桶,解为[3(8-3)+ 3*(8 -3)+ 2*(8-2)] / 2 = 42 / 2 = 21。
下面是对该方法的更详细解释:
同一桶内的任何两个整数在AND运算下比在XOR运算下具有更高的值,因为AND运算保留最大设置位,而XOR运算将其变为0。
现在取两个不同桶中的整数,其中一个的最大设置位比另一个高,这意味着这两个数之间的最大设置位出现在一个中,而另一个中没有,因此在AND运算下变为0,但在XOR运算下被保留,因此XOR导致更高的最大设置位。
XOR比AND产生更高结果的对的数量正好是不在同一桶中的对的数量。
假设我们总共有n个整数,某个桶中有r个整数,这个桶中的r个整数都可以与其他桶中的任何一个(n-r)整数配对,但不能与同一个桶中的任何r-1个整数配对,这就为异或比与产生更大整数的对的计数贡献了r *(n-r)。
然而,这会对每一对计数两次,例如,当我们比较1001和110时,我们对第4和第3个最高设置位为1的桶的分析将为这一对增加1,因此最后我们必须除以2。
进一步举例:
以下是所有第三位为最高设置位的整数:4、5、6、7或100、101、110和111(以二进制表示)。
以下是第二位为最高设置位的所有器件:二进制的2、3或10、11。
取任意一对具有相同的最高置位,我会任意选择6和7。(110,111)= 110 = 6.异或运算(110,111)= 001。因此AND运算产生比XOR高的结果。在每种情况下,XOR将最高设置位从1转换为0,AND将保持其为1,因此在每种情况下,AND将产生比XOR更高的结果。
从单独的存储桶中取对,对中设置位最高的位仅在两个整数之一中设置(因为这是我们分组的依据),因此在AND下,该位变为0,而在XOR下,该位保持为1。由于XOR运算使输出具有比AND更大的设置位,因此在XOR下得到的整数更高。