剑指OFFER----56-1、数组中只出现一次的两个数字(js实现)

题目

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字,要求时间复杂度为O(N),空间复杂度为O(1)

leetcode链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/


思想

第一步: 把所有的元素进行异或操作,最终得到一个异或值。因为是不同的两个数字,所以这个值必定不为0;

第二步: 因为有两个不同的数,那么这两个数在某一位上肯定是不同的,第一步异或出来的为1的进制位说明在这一位上两个数不同,这种位数有很多,我们只需要取其中一个就行了,记为tag

第三步: 通过与这个tag进行与操作,如果为0的分为一个数组,为1的分为另一个数组。这样就把问题降低成了:“有一个数组每个数字都出现两次,有一个数字只出现了一次,求出该数字”。对这两个子问题分别进行全异或就可以得到两个解。也就是最终的数组了。

复杂度分析: 时间复杂度O(N),空间复杂度O(1)


代码

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var singleNumbers = function (nums) {
  let xor = 0
  for (const num of nums) {
    xor ^= num
  }
  // 找第一个不同的二进制位,肯定有一位不同的
  let tag = 1
  while (!(tag & xor)) tag <<= 1
  // 拆分成两个数
  let num1 = 0
  let num2 = 0
  for (const num of nums) {
    if (num & tag) {
      num1 ^= num
    } else {
      num2 ^= num
    }
  }
  return [num1, num2]
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值