137. 只出现一次的数字 II

题目来源:137. 只出现一次的数字 II // 给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
/** 方法一:哈希表
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function(nums) {
    let map = new Map();
    let res;
    for(let num of nums){
        freq.set(num, (freq.get(num)||0) +1 )
    }
    for(let [m,c] of map){
        if(c==1){
            res = m;
            break;
        }
    }
    return res;
}; 


/** 方法二:依次确定每一个二进制位
 * @param {number[]} nums
 * @return {number}
 */
 var singleNumber = function(nums) {
    let res = 0;
    for(let i = 0;i<32;i++){
        let total = 0;
        for(let num of nums){
            total += (num>>i)&1;
        }
        
        if(total%3 != 0){
            res |= 1<<i;
        }
    }
    return res;
}; 
let nums = [2,2,3,2]
console.log(nums, singleNumber(nums))


nums =[0,1,0,1,0,1,99]
console.log(nums, singleNumber(nums))


/** 状态机2
 * @param {number[]} nums
 * @return {number}
 */
 var singleNumber = function(nums) {
    let a = 0,b=0;
    for(let num of nums){
        let aNext = ~a&b&num|a&~b&~num;
        let bNext = ~a&~b&num|~a&b&~num;
        a = aNext;
        b = bNext;
    }
    return b;
};

补充:

状态机2来推导公式:

  3 种状态   存储    输入   结果    ab      c     ab       00      1     01       01      1     11 (注意这个地方a是1),所以a= ~a&b&c    11      1     00

 

   00      0     00       01      0     01    11      0     11 (注意这个地方a是1),所以a=a&b&~c 我们看到有两个地方a是1,所以 a= ~a&b&c|a&b&~c,如果abc那个是1我们就用原来的字符表示,如果是0就取反,多个是1的地方用运算符|表示。



再比如有4个地方b是1,他们分别是

 

00      1     01        ~a & ~b & c 01      1     11        ~a & b & c 01      0     01        ~a & b & ~c 11      0     11         a & b & ~c 所以b=~a & ~b & c | ~a & b & c | ~a & b & ~c | a & b & ~c。



// 示例 1: // 输入:nums = [2,2,3,2] // 输出:3 // 示例 2: // 输入:nums = [0,1,0,1,0,1,99] // 输出:99 

 

// 提示: // 1 <= nums.length <= 3 * 104 // -231 <= nums[i] <= 231 - 1 // nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 

 

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

 

上一篇:信息学奥赛一本通(1208:2的幂次方表示)


下一篇:两道腾讯的面试真题,考验C++对象模型的理解