剑指 Offer 56 - I. 数组中数字出现的次数

1. 题 目 描 述 \color{DodgerBlue}{1.题目描述} 1.

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

示例 1:

输入:nums = [4,1,4,6];
输出:[1,6] 或 [6,1]

示例 2:

输入: nums = [1,2,10,4,1,4,3,3]
输出: [2,10] 或 [10,2]

2. 解 题 思 路 \color{DodgerBlue}{2.解题思路} 2.

  1. 由于时间复杂度和空间复杂度的限制,所以使用异或是最好的
  2. 异或运算中:a^a=0, a^0=a, aba=aab=b
  3. 根据第2点,数组中所有数进行异或的结果就是两个不同数的异或结果
  4. 现在就是如何找出这两个数
  5. (重点)由于异或的本质是二进制的运算,结果就是两个不同数的二进制值的异或运算,所以我们可以根据整个数组的异或结果(也就是这两个数的异或结果)从右向左数出现的第一个不同的的位置(这个位置两个数的二进制运算的结果为1)开始去对数组进行分组(这样就保证分成两组),这样也可以保证两个不同的数可以分到两个不同的数组
  6. 最后分别对两个数组进行异或,就可以得到这两个不同的数。

3. J a v a S c r i p t 代 码 \color{DodgerBlue}{3.JavaScript代码} 3.JavaScript

var singleNumbers = function (nums) {
  let bitRes = 0; // 二进制结果
  let index = 0; //不同数的位置
  // 循环数组得到最终二进制结果
  for (let i of nums) {
    bitRes ^= i;
  }
  // 判断两个异或的数在哪个位置不一样,也就是哪个位置为1
  // 与&运算,两个为1,结果才为1,否则都为0
  // 只要为0,表示该位置都是0,当结果为1的时候,就是不同的位置index
  while ((bitRes & 1) === 0) {
    index += 1;
    bitRes >>= 1; // 右移一位,除以2,移除右边一位,左边高位补0
  }
  // 开始分组计算
  let res1 = 0;
  let res2 = 0;
  // 将数组中每个数的二进制右移index位,然后与1想与,根据结果的不同来划分两个数组。
  // 这里划分数组的方式是通过异或的方式
  for (item of nums) {
    if (((item >> index) & 1) === 0) {
      res1 ^= item;
    } else {
      res2 ^= item;
    }
  }
  return [res1, res2];
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值