leetcode982. 按位与为零的三元组(双百解法)

该博客探讨了LeetCode 982题目的两种解法:使用哈希表的暴力解法和位运算优化解法。通过位运算确定上界和掩码,实现更快的枚举和结果累加,从而提高空间和时间效率,最终达到接近双百的解决方案。

题目链接:https://leetcode-cn.com/problems/triples-with-bitwise-and-equal-to-zero/

题意:

给定一个整数数组 A,找出索引为 (i, j, k) 的三元组,使得:

0 <= i < A.length
0 <= j < A.length
0 <= k < A.length
A[i] & A[j] & A[k] == 0,其中 & 表示按位与(AND)操作符。

方法一:哈希表暴力解 

class Solution {
public:
    int countTriplets(vector<int>& nums) {
        int total = 0;
        unordered_map<int,int> mp1;//哈希表1,<数字,出现次数>
        unordered_map<int,int> mp2;//哈希表2,<两数与的结果,出现次数>
        for(int& num:nums)//更新哈希表1
        {
            mp1[num]++;
        }
        int len = nums.size();//统计nums的长度
        for(int i=0;i<len;i++)//更新哈希表2
        {
            for(int j=0;j<len;j++)
            {
                mp2[nums[i]&nums[j]]++;
            }
        }
        for(auto iter1=mp1.begin();iter1!=mp1.end();iter1++)//利用迭代器,统计最后结果
        {
            for(auto iter2=mp2.begin();iter2!=mp2.end();iter2++)
            {
                if((iter1->first&iter2->first)==0) 
                    total+=iter2->second*iter1->second;
            }
        }
        return total;
    }
};

 方法二:位运算,通过确定上界,来确定掩码,向下枚举每种情况,最后对结果进行累加

class Solution {
public:
    int countTriplets(vector<int>& nums) {
        int total = 0;
        int k = 1;//用来确定掩码,掩码是由全1组成的数字
        for(int& num:nums)//确定上界,进而确定掩码
        {
            while(k<=num)
            {
                k<<=1;
            }
        }
        unordered_map<int,int> mp;//哈希表,<和key值进行与操作能等于0的数字,这样的数字由多少>
        for(int& num:nums)
        {
            int mask = (k-1)^num;//k-1是掩码,格式类似于0001111111...111111,^进行异或操作,找到剩下的那些1
            int i=mask;
            for(int i=mask;i!=0;i=(i-1)&mask)//向下遍历枚举每个能和num进行与操作结果等于0的数字
            {
                mp[i]++;
            }
            mp[0]++;//0与任何数进行与操作,结果都是0,所以必须最后再加上一次
        }
        for(int& a:nums)//遍历枚举,找到最后要返回的结果
        {
            for(int& b:nums)
            {
                total+=mp[a&b];//确定最后一个数字可以有多少种取法
            }
        }
        return total;
    }
};


转为vector实现哈希表,提高空间效率和时间效率,最后的结果提升到将近双百 

class Solution {
public:
    int countTriplets(vector<int>& nums) {
        int total = 0;
        int k = 1;//用来确定掩码,掩码是由全1组成的数字
        for(int& num:nums)//确定上界,进而确定掩码
        {
            while(k<=num)
            {
                k<<=1;
            }
        }
        vector<int> mp(k,0);//哈希表,<和key值进行与操作能等于0的数字,这样的数字由多少>
        for(int& num:nums)
        {
            int mask = (k-1)^num;//k-1是掩码,格式类似于0001111111...111111,^进行异或操作,找到剩下的那些1
            int i=mask;
            for(int i=mask;i!=0;i=(i-1)&mask)//向下遍历枚举每个能和num进行与操作结果等于0的数字
            {
                mp[i]++;
            }
            mp[0]++;//0与任何数进行与操作,结果都是0,所以必须最后再加上一次
        }
        for(int& a:nums)//遍历枚举,找到最后要返回的结果
        {
            for(int& b:nums)
            {
                total+=mp[a&b];//确定最后一个数字可以有多少种取法
            }
        }
        return total;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值