给你一个下标从 0 开始的正整数数组 nums 和一个正整数 k 。
如果满足下述条件,则数对 (num1, num2) 是 优质数对 :
num1 和 num2 都 在数组 nums 中存在。
num1 OR num2 和 num1 AND num2 的二进制表示中值为 1 的位数之和大于等于 k ,其中 OR 是按位 或 操作,而 AND 是按位 与 操作。
返回 不同 优质数对的数目。
如果 a != c 或者 b != d ,则认为 (a, b) 和 (c, d) 是不同的两个数对。例如,(1, 2) 和 (2, 1) 不同。
注意:如果 num1 在数组中至少出现 一次 ,则满足 num1 == num2 的数对 (num1, num2) 也可以是优质数对。
示例 1:
输入:nums = [1,2,3,1], k = 3
输出:5
解释:有如下几个优质数对:
示例 2:
输入:nums = [5,1,1], k = 10
输出:0
解释:该数组中不存在优质数对。
这题很难啊,个人建议可以学习一下,思路就是,我们肯定是要去重的,所以做一个排序,然后去重,之后,我们统计每个数二进制1的个数,解题代码如下:
int cmp(const void* a, const void* b) {
return *(int*)a - *(int*)b;
}
long long countExcellentPairs(int* nums, int numsSize, int k){
long long re=0;
int r[32];
int newsize = 0;
qsort(nums, numsSize, sizeof(int), cmp); //排序原数组
for (int i = 1; i < numsSize; i++) {
if (nums[i] != nums[newsize]) nums[++newsize] = nums[i];
}//去重原数组
++newsize;
// printf("newsize %d ",newsize);
numsSize=newsize;
for(int i=0;i<32;i++){
r[i]=0;
}
for(int i=0;i<numsSize;i++){
int count=0;
int t=nums[i];
while(t){
if(t&1){
count++;
}
t=t>>1;
}
r[count]++;
}
// for(int i=0;i<32;i++){
// printf("%d ",r[i]);
// }
for(int i=0;i<32;i++){
if(r[i]!=0){
for(int j=i;j<32;j++){
if(r[j]!=0){
if(i+j>=k&&i==j){
re=re+(r[j])*(r[j]-1)+r[j];
}
else if(i+j>=k){
re=re+r[i]*r[j]*2;
}
}
}
}
}
return re;
}