题目描述
对于任意两个正整数A和B,定义它们之间的差异值和相似值:
**差异值:**A、B转换成二进制后,对于二进制的每一位,对应位置的bit值不相同则为1,否则为0;
**相似值:**A、B转换成二进制后,对于二进制的每一位,对应位置的bit值都为1则为1,否则为0;
现在有n个正整数A0到A(n-1),问有多少(i, j) (0<=i<j<n),Ai和Aj的差异值大于相似值。
假设A=5,B=3;则A的二进制表示101;B的二进制表示011;
则A与B的差异值二进制为110;相似值二进制为001;
A与B的差异值十进制等于6,相似值十进制等于1,满足条件。
输入描述
一个n接下来n个正整数
数据范围:1<=n<=105,1<=A[i]<230
输出描述
满足差异值大于相似值的对数
** 示例1
输入
4
4 3 5 2
输出
4
说明>
满足条件的分别是(0,1)(0,3)(1,2)(2,3),共4对。
思路
1. 问题本质转化
统计满足 A[i] ^ A[j] > A[i] & A[j](0≤i<j<n)的数对数量,核心规律为:
两数异或值大于与值 ⇨ 两数的二进制最高有效位不同。
- 若最高位不同:异或的最高位为较高的那个位(值为1),与的最高位为0 → 异或>与,满足条件;
- 若最高位相同:与的最高位为该位(值为1),异或的最高位低于该位 → 异或≤与,不满足条件。
2. 核心解法(两种高效思路)
解法1:正面统计(最优)
- 步骤1:统计每个二进制最高有效位下的数的个数(如用
31 - Math.clz32(num)计算数的最高位位置); - 步骤2:累加所有“不同最高位组合”的数对数量(即遍历所有
i<j,计算count[i] * count[j],count[bit]为最高位bit的数的个数)。
解法2:补集思想
- 步骤1:计算所有可能的数对总数
total = n*(n-1)/2; - 步骤2:统计“最高位相同”的数对数量(不满足条件):对每个最高位bit,计算
count[bit]*(count[bit]-1)/2并求和; - 步骤3:答案 = 总数 - 不满足条件的数对数量。
3. 关键细节
- 最高位计算:利用
Math.clz32(num)求32位二进制前导0个数,31 - 前导0数即为最高位位置(适配A[i]<2^30的约束); - 数值溢出:n=1e5时数对总数约5e9,需用BigInt或适配大整数的类型避免溢出;
- 时间复杂度:O(n + 30×30)(n为数字个数,30为二进制最高位范围),完全适配n=1e5的大数据量。
4. 核心思维
- 位运算题优先“按位分组”降维:将n级问题转化为30级(二进制位数)的小规模问题;
- 直接统计困难时,优先用“补集思想”简化计算。
代码
function solution() {
const n = Number

最低0.47元/天 解锁文章
21

被折叠的 条评论
为什么被折叠?



