一【题目类别】
- 位运算
二【题目难度】
- 困难
三【题目编号】
- 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
六【题目提示】
- 1 < = n u m s . l e n g t h < = 1000 1 <= nums.length <= 1000 1<=nums.length<=1000
- 0 < = n u m s [ i ] < 2 16 0 <= nums[i] < 2^{16} 0<=nums[i]<216
七【解题思路】
- 常规的思路很好想,使用 O ( n 3 ) O(n^3) O(n3)的时间复杂度的算法就可以,但是肯定会超时,所以我们应该想办法进行优化
- 首先我们定义一个哈希表,长度为 2 16 2^{16} 216,因为数组元素最大为 2 16 2^{16} 216,数组中任意两个元素&的结果也不会超过 2 16 2^{16} 216,而且,哈希表的下标就是数组中任意两个元素&的结果,哈希表下标对应的值就是数组中任意两个元素&的结果对应的次数
- 然后我们再遍历数组中的每个元素,如果其与哈希表下标&的结果是0,说明这个三元组就是我们要找的三元组,我们只需要保存其出现的次数,就是满足条件的三元组的个数,这样我们就将时间复杂度降低为 O ( n 2 + 2 16 n ) O(n^2+2^{16}n) O(n2+216n)
- 最后返回结果即可
八【时间频度】
- 时间复杂度: O ( n 2 + 2 16 n ) O(n^2+2^{16}n) O(n2+216n),其中 n n n为传入数组的长度
- 空间复杂度: O ( 2 16 ) O(2^{16}) O(216)
九【代码实现】
- Java语言版
class Solution {
public int countTriplets(int[] nums) {
int[] count = new int[1 << 16];
int length = nums.length;
int res = 0;
for(int i = 0;i<length;i++){
for(int j = 0;j<length;j++){
count[nums[i] & nums[j]]++;
}
}
for(int i = 0;i<length;i++){
for(int j = 0;j < (1 << 16);j++){
if((j & nums[i]) == 0){
res += count[j];
}
}
}
return res;
}
}
- C语言版
int countTriplets(int* nums, int numsSize)
{
int* count = (int*)calloc((1 << 16),sizeof(int));
int res = 0;
for(int i = 0;i<numsSize;i++)
{
for(int j = 0;j<numsSize;j++)
{
count[nums[i] & nums[j]]++;
}
}
for(int i = 0;i<numsSize;i++)
{
for(int j = 0;j< (1 << 16);j++)
{
if((j & nums[i]) == 0)
{
res += count[j];
}
}
}
return res;
}
- Python语言版
class Solution:
def countTriplets(self, nums: List[int]) -> int:
count = Counter((x & y) for x in nums for y in nums)
res = 0
for x in nums:
for j,k in count.items():
if (x & j) == 0:
res += k
return res
- C++语言版
class Solution {
public:
int countTriplets(vector<int>& nums) {
vector<int> count(1 << 16);
int res = 0;
for(int x : nums)
{
for(int y : nums)
{
count[x & y]++;
}
}
for(int x : nums)
{
for(int j = 0;j < (1 << 16);j++)
{
if((x & j) == 0)
{
res += count[j];
}
}
}
return res;
}
};
十【提交结果】
-
Java语言版
-
C语言版
-
Python语言版
-
C++语言版