[位运算] 剑指 Offer II 004. 只出现一次的数字

142 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情

每日刷题 2022.08.18

题目

  • 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。 请你找出并返回那个只出现了一次的元素。

示例

  • 示例1
输入: nums = [2,2,3,2]
输出: 3
  • 示例2
输入: nums = [0,1,0,1,0,1,100]
输出: 100

提示

  • 1 <= nums.length <= 3 * 10^4
  • -2^31 <= nums[i] <= 2^31 - 1
  • nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次

进阶: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

解题思路

  • 根据题意分析:数组中只有一个元素是出现一次的,其他的都是出现了三次的。
  • 简单的做法就是:使用map集合记录每一个数值出现的次数,将出现次数为1的直接输出就可以了。

位运算

  • 查看本题的数据范围,整数。具有32位。
  • 那么我们可以将nums中的每一个数值拆分成32位,将所有出现的进制位进行累加,最终将每一个进制位模3,求得只出现一次的。
  • 记录结果的方式,依旧可以使用上次使用的方法,将1 << bit(1左移bit位,之后再或运算)

AC代码

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
  // 位运算,常数的空间,就可以声明一个32位大小的空间,这个不算额外的空间
  let cnt = new Array(32).fill(0);
  // 整数:32位,所以只要开32位就可以了
  const n = nums.length;
  for(let i = 0; i < n; i++) {
    let cur = nums[i];
    for(let j = 0; j < 32; j++) {
      cnt[j] += cur & 1;
      cur = cur >> 1;
    }
  }
  // console.log(cnt)
  let res = 0;
  for(let i = 0; i < 32; i++) {
    if(cnt[i] % 3 === 1) {
      res += 1 << i;
    }
  }
  return res;
};