力扣每日一题982.按位与零的三元组
题目
给你一个整数数组 nums ,返回其中 按位与三元组 的数目。
按位与三元组 是由下标 (i, j, k) 组成的三元组,并满足下述全部条件:
0 <= i < nums.length
0 <= j < nums.length
0 <= k < nums.length
nums[i] & nums[j] & nums[k] == 0 ,其中 & 表示按位与运算符。
示例 1:
输入:nums = [2,1,3]
输出:12
解释:可以选出如下 i, j, k 三元组:
(i=0, j=0, k=1) : 2 & 2 & 1
(i=0, j=1, k=0) : 2 & 1 & 2
(i=0, j=1, k=1) : 2 & 1 & 1
(i=0, j=1, k=2) : 2 & 1 & 3
(i=0, j=2, k=1) : 2 & 3 & 1
(i=1, j=0, k=0) : 1 & 2 & 2
(i=1, j=0, k=1) : 1 & 2 & 1
(i=1, j=0, k=2) : 1 & 2 & 3
(i=1, j=1, k=0) : 1 & 1 & 2
(i=1, j=2, k=0) : 1 & 3 & 2
(i=2, j=0, k=1) : 3 & 2 & 1
(i=2, j=1, k=0) : 3 & 1 & 2
示例 2:
输入:nums = [0,0,0]
输出:27
思路
- 本题即需要从三元组中选出3个数,使得这三个数求与运算得0
- 我们不妨列出这三个数字的所有两两排列组合(可重复抽样)之后位运算的结果,并对结果进行统计
- 简单观察下可以发现,我们只需要计算用第三个数字与上述统计结果中的键与运算,取结果为0的键的值进行计数,最后求和,即是题目所需。
代码 (来自评论区大佬施舒阳)
class Solution:
def countTriplets(self, nums: List[int]) -> int:
c = collections.Counter(i&j for i in nums for j in nums)
return sum(c[j] for i in nums for j in c if i&j==0)
总结
- 这道题是hard,但是这种偏暴力的做法可以通过,可能很大原因上是因为生成器,当从别处调用的生成器暂时返回后,生成器会记住上次的返回点;当对该生成器再次调用(使用next()方法)时,它会从生成器上次的返回点继续执行,而不是从头开始执行该被调函数;此外,上次调用返回时的“上下文”在下次调用时也会恢复。这题应该有更简单的做法,诸如枚举 + 子集优化或快速沃尔什变换。