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),借助一个辅助数组,其长度是常数。

  • 相关阅读:
    BurpSuite—-Spider模块(蜘蛛爬行)
    BurpSuite系列(一)----Proxy模块(代理模块)
    hadoop HA集群搭建步骤
    HBase详解
    MapReduce两种执行环境介绍:本地测试环境,服务器环境
    HBase性能优化方法总结
    HDFS原理解析
    ZooKeeper 典型应用场景
    Redis总结
    基于Apache Curator框架的ZooKeeper使用详解
  • 原文地址:https://www.cnblogs.com/Howfars/p/13365560.html
Copyright © 2011-2022 走看看