企业前端面试题——企业面试真题22

找出数组中两个只出现一次的数字:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(1).要求:给出算法描述,并且给出核心代码

已知:

  • 相同的两个数字按位异或, 结果为0
  • 一个数字跟0按位异或, 结果为其本身

思路:

根据题目的表述, 有数组如下:
[A1, A2, A3, A4, A5, A6, A7, A8]
这当中有两个独立数字, 其余均为成对出现, 因此数组长度必然为偶数

第一步, 我们将A1~A8所有数字, 全部异或在一起, 即:

A1^A2^A3^A4^A5^A6^A7^A8

由于已知条件, 那么相同数字将变成0, 相互抵消

最终, 结果等价于两个独立数字的异或结果.

假设得到的结果为: 0001 0100 (二进制)

var r1 = arr[0]^arr[1];
for(var i=2; i<arr.length; i++){
    r1 = r1^arr[i]
}

第二步, 由第一步结果可以得知, 两个独立数字, 在bit位的第3位上不同的.

其实第5位也不相同, 但我们只看一个就够了.

那就意味着, 两个独立数字, 分别为

xxxx x1xx 独立数字 M
xxxx x0xx 独立数字 N

第三步, 构造出一个检查数字, 类似于下面这样:

0000 0100 检查数字W
var w = 1;
while( r1&w != w) {
    w<<1;
}

第四步, 找出数组中, 所有第3位都等于1的数字

检测方法, 就是跟 数字W按位与

若 A&W == 1 , 则表示 数字A的第3位是1

找出的所有数字个数, 必定为奇数, 因为这当中包含了相同的数字, 和某一个独立数字 M
var M = 0;
for(var i=0; i<arr.length; i++){
    if(arr[i]&w == 1) M = M^arr[i];
}

第五步, 根据第一步的方法, 将找出的这些数字全部异或, 则得出独立数字M

独立数字M已经得到

第六步, 数字M与第一步结果进行异或, 则得出独立数字N

var N = M^r1;

 

完整代码

var r1 = arr[0]^arr[1];
for(var i=2; i<arr.length; i++){
    r1 = r1^arr[i]
}
var w = 1;
while( r1&w != w) {
    w<<1;
}
var M = 0;
for(var i=0; i<arr.length; i++){
    if(arr[i]&w == 1) M = M^arr[i];
}
var N = M^r1;

console.log(M, N);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值