LeetCode——982. 按位与为零的三元组

一、题目

LeetCode——982. 按位与为零的三元组_第1张图片
LeetCode——982. 按位与为零的三元组_第2张图片
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/triples-with-bitwise-and-equal-to-zero/description/

二、C++解法

我的思路及代码

枚举

我们首先采用一个哈希表来存储任意俩俩按位与后的结果的次数,然后再遍历哈希表让将这个结果和第三个数字继续按位与,符合要求的就让计数器增加哈希表中的次数,这样的做法比直接暴力遍历会降低一定的时间复杂度。

class Solution {
public:
    int countTriplets(vector<int>& nums) {
        int ans=0;
        unordered_map<int,int> map;
        for(int i=0;i<nums.size();i++){
            for(int j=0;j<nums.size();j++){
                map[nums[i]&nums[j]]++;
            }
        }
        for(auto [key,vaule]:map){
            for(int it:nums)
                if(!(it&key)){
                    ans+=map[key];
                }
        }
        return ans;
    }
};
  • 时间复杂度:O(n2+C⋅n),其中 n 是数组 nums 的长度,C 是数组 nums 中的元素范围,在本题中 C=216
  • 空间复杂度:O(C),即为数组(或哈希表)需要使用的空间

官方参考代码

枚举 + 子集优化

LeetCode——982. 按位与为零的三元组_第3张图片

class Solution {
public:
    int countTriplets(vector<int>& nums) {
        vector<int> cnt(1 << 16);
        for (int x: nums) {
            for (int y: nums) {
                ++cnt[x & y];
            }
        }
        int ans = 0;
        for (int x: nums) {
            x = x ^ 0xffff;
            for (int sub = x; sub; sub = (sub - 1) & x) {
                ans += cnt[sub];
            }
            ans += cnt[0];
        }
        return ans;
    }
};
  • 时间复杂度:O(n2+C⋅n),其中 n 是数组 nums 的长度,C 是数组 nums 中的元素范围,在本题中 C=216
  • 空间复杂度:O©,即为数组(或哈希表)需要使用的空间

野生大佬参考代码

快速沃尔什变换

我看不懂但是我大受震撼

#include

__attribute__((no_sanitize_address,no_sanitize_memory))
__attribute__((target("avx2")))
void fwt(int* seq, int n) {
    const auto end = seq + n;
    for (int i = 1;i < 8 && i < n;i *= 2)
        for (auto j = seq;j != end;j += i)
            for (const auto k = j + i;j < k;++j)
                *j += j[i];
    const int m = n / 8;
    const auto l = reinterpret_cast<__m256i*>(seq);
    const auto r = reinterpret_cast<__m256i*>(end);
    for (int i = 1;i < m;i *= 2)
        for (auto j = l;j != r;j += i)
            for (const auto k = j + i;j < k;++j)
                *j = _mm256_add_epi32(*j, j[i]);
}

class Solution {
public:
    int countTriplets(const vector<int>& nums) {
        const int m = *max_element(nums.begin(), nums.end());
        const int l = m > 0 ? 1 << (32 - __builtin_clz(m)) : 1;
        alignas(32) int seq[l];
        fill_n(seq, l, 0);
        for (int e : nums)
            ++seq[e];
        fwt(seq, l);
        int ans = 0;
        for (int i = 0;i <= m;++i)
            ans += (1 - 2 * __builtin_parity(i)) * seq[i] * seq[i] * seq[i];
        return ans;
    }
};

时间复杂度:O(n+ClogC)

你可能感兴趣的:(力扣,leetcode,算法)