zoukankan      html  css  js  c++  java
  • 剑指Offer_#56-II_ 数组中数字出现的次数II

    剑指Offer_#56-II_ 数组中数字出现的次数II

    Contents

    题目

    在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。
    示例 1:

    输入:nums = [3,4,3,3]
    输出:4

    示例 2:

    输入:nums = [9,1,7,9,7,9,7]
    输出:1

    限制:

    1 <= nums.length <= 10000
    1 <= nums[i] < 2^31

    思路分析

    思路是统计数字的二进制表示中每一位出现的次数。

    • 对于出现3次的数字,每个二进制位也出现3次;多组出现3次的数字叠加,每个二进制位出现次数是3的倍数。
    • 再考虑只出现一次的数字,即我们的目标数字。目标数字中,出现1的二进制位会增加到之前的统计次数中,使得这个位置出现1的总次数不再是3的倍数。

    算法流程

    1. 遍历数组,对于每个元素,循环右移位,通过掩码1获取到二进制表示中每一位1出现的次数,保存到一个辅助数组中,索引表示第几位,元素表示出现的次数。
    2. 遍历刚才的辅助数组,看每个元素对3取余的结果
      • 若为0说明这一位出现了3的整数倍次,必然没有在目标数字中出现过,所以不计算
      • 若不为0,说明这位数字出现在目标数中,res加上digit,也就是当前二进制位的数量级(2n

    解答

    class Solution {
        public int singleNumber(int[] nums) {
            int res = 0;
            //二进制中每一位数字的数量级
            int digit = 1;
            //统计二进制表示中每一位出现的总个数
            int[] numTimes = new int[32];
            for(int num:nums){
                for(int i = 0; i <= 31;i++){
                    //如果第i位是1,那么help[i]增加1
                    numTimes[i] += (num & 1);
                    //继续统计下一位
                    num >>= 1;
                }
            }
            //遍历help[]数组
            for(int times:numTimes){
                res += digit * (times % 3);
                digit <<= 1;
            }
            return res;
        }
    }

    复杂度分析

    时间复杂度:O(n),两层循环中,第二层循环次数是常数,所以还是O(n)。
    空间复杂度:O(1),借助一个辅助数组,其长度是常数。

  • 相关阅读:
    MEAN: AngularJS + NodeJS的REST API开发教程
    什么是MEAN全堆栈javascript开发框架
    fputcsv 导出excel,解决内存、性能、乱码、科学计数法问题
    React 高德地图画点画区域放大缩小
    React 拖动布局
    React+TypeScript搭建项目
    js 运算符优先级
    for...in 与 for...of
    前端面试点记录
    Vue 高德地图 路径规划 画点
  • 原文地址:https://www.cnblogs.com/Howfars/p/13365560.html
Copyright © 2011-2022 走看看