【剑指Offer】整数(五)二进制 - 只出现一次的数字II - JavaScript

154 阅读2分钟

嗨!~ 大家好,我是YK菌 🐷 ,一个微系前端 ✨,爱思考,爱总结,爱记录,爱分享 🏹,欢迎关注我呀 😘 ~ [微信公众号:YK菌]

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 7 天,点击查看活动详情

今天继续来刷《剑指offer(专项突破版)》,原书是Java版本的,这里就是以JavaScript角度来看这些算法题。

剑指 Offer II 004. 只出现一次的数字

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

本题与主站137. 只出现一次的数字 II相同。

分析

上一篇我们将重复两次的情况做出来了【剑指Offer】整数(四)二进制 - 只出现一次的数字I - JavaScript - 掘金 (juejin.cn),今天来看看重复三次的情况,这种情况稍微难一点。

如果不考虑空间复杂度,采用上一篇说的setmap也可以完成,但是使用异或运算就做不到了。相同的数字异或自己三次得到的还是自己,所以将数组中所有数字依次进行异或操作不能消除出现三次的数字。

题目中有一个条件,就是限制了231 <=nums[i]<=231 1-2^{31} <= nums[i] <= 2^{31} - 1,也就是说整数只有32位(在Java中整数类型int就是32位的,而在JavaScript中没有整型,只有Number类型,是64位的浮点数类型)

所以说数组中的元素都是由32位0或1组成的。可以将数组中所有数字的同一位的数位进行相加,如果是出现三次的数字,数位相加后一定是三的倍数(0+0+0=00+0+0=01+1+1=31+1+1=3)。

  1. 如果数组中所有数的第i个数位相加之和能被3整除,那么只出现一个的数字的第i个数位一定是0
  2. 如果数组中所有数的第i个数位相加之和被3除余1,那么只出现一个的数字的第i个数位一定是1

题解

  • 通过位运算((x >> i) & 1) 得到 x 的第 i 个二进制位

  • |=表示按位进行或运算,所以可以通过位运算x |= (1 << i) ,将x(1 << i)(将1左移i个位置)按位或,可以将x的第i位设置为1

/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
    let result = 0
    for(let i = 0; i < 32; i++){
        let bitSum = 0
        for (num of nums){
            bitSum += ((num >> i) & 1)
        }
        if (bitSum % 3 !== 0){
            result |= (1 << i)
        }
    }
    return result
};

image.png

最后,欢迎关注我的专栏,和YK菌做好朋友