【OD机试题笔记】二进制差异数

题目描述

对于任意两个正整数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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值