跳到主要内容

982.按位与为零的三元组

· 阅读需 3 分钟

1、题干

给你一个整数数组 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

 

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] < 216

先暴力打个卡睡觉

2、思路

本题可以用三数之和的思路暴力解题。先用哈希表 map 存储所有二元组按位与的结果与出现次数,再枚举数组 numsmap 所有的键,如果二者位与结果为 0 就累计其次数

这种暴力思路会超时吗?可以稍微分析下时间复杂度:

  • 第一个嵌套循环的时间复杂度为 O(n2)O(n^2),其中 nn 为数组 nums 长度,由于 n<=1000n <= 1000,整体量级最多为 10610^6,基本不会超时;
  • 第二个嵌套循环的时间复杂度为 O(nm)O(nm),其中 mm 为哈希表键的个数,由于 nums[i] 小于 2162^{16},所以二元组按位与的结果个数不会超过 2162^{16},即哈希表的键数 m<=65536m<=65536,整体量级最多为 61076*10^7,大概率能过

3、代码

function countTriplets(nums: number[]): number {
const map = new Map();
for (const x of nums) {
for (const y of nums) {
const z = x & y;
map.set(z, (map.get(z) || 0) + 1);
}
}

let ans = 0;
for (const x of nums) {
for (const [y, c] of map) {
if (!(x & y)) ans += c;
}
}

return ans;
};

4、复杂度

  • 时间复杂度:O(nm)O(nm)
  • 空间复杂度:O(m)O(m)

5、执行结果

image.png