📌  相关文章
📜  不能形成任何对的元素总数为2的幂的元素的计数(1)

📅  最后修改于: 2023-12-03 15:35:55.417000             🧑  作者: Mango

不能形成任何对的元素总数为2的幂的元素的计数

这里介绍一种计算不能形成任何对的元素总数为2的幂的元素的计数的方法,假设给定一个长度为N的非空整数数组arr[]

算法思路

首先,一对元素(a[i], a[j])可以形成2的幂的总数,当且仅当a[i] ^ a[j]为2的幂。

假设所有的元素都可以形成若干个这样的对。我们把这些元素分成两类:

  • 类别A:a[i]为2的幂,a[j]为非2的幂。

  • 类别B:a[i]为非2的幂,a[j]为2的幂。

对于类别A,如果除去a[i]后剩下的元素个数为M,而M又都为2的幂,那么a[i]也不能形成任何对。因为无论如何组合,都只能得到(a[i], a[i]), (a[i], a[k])这两种情况(k为除去a[i]后的剩余元素),不能构成2的幂数量。

同样的,对于类别B,如果除去a[j]后剩下的元素个数为M,而M又都为2的幂,那么a[j]也不能形成任何对。

考虑到一个元素只有可能被算一次,我们可以用哈希表来记录每个元素的出现次数,这样只需要遍历数组两次,就可以得到所有的不能形成任何对的元素的总数。

代码实现

下面是Python实现的代码,其中get_pow2_count()函数返回不能形成任何对的元素总数,count_pow2_pairs()函数返回所有能够形成2的幂数量的元素对。

from collections import defaultdict

def count_pow2_pairs(arr):
    n = len(arr)
    count = 0
    cnts = defaultdict(int)
    for i in range(n):
        cnts[arr[i]] += 1
    for i in range(n - 1):
        for j in range(i + 1, n):
            if (arr[i] ^ arr[j]) & (arr[i] ^ arr[j] - 1) == 0:
                count += 1
    return count

def get_pow2_count(arr):
    cnts = defaultdict(int)
    pow2s = set([2 ** i for i in range(31)])
    for a in arr:
        cnts[a] += 1
    for a in arr:
        if cnts[a] > 1:
            continue
        if a in pow2s:
            continue
        if (a & a - 1) == 0 and cnts.get(0, 0) < 2:
            continue
        if (a & a - 1) != 0 and cnts.get(a ^ a - 1, 0) > 0:
            continue
        return 1
    return 0
总结

以上算法的时间复杂度为$O(n^2)$。对于较大的数组会有性能问题,但对于现代计算机和一般的数组长度,可以接受。