137. Single Number II

Posted 小河沟大河沟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了137. Single Number II相关的知识,希望对你有一定的参考价值。

欢迎fork and star:Nowcoder-Repository-github

137. Single Number II

题目

 Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? 

解析

  • 由于除去目标元素target之外,所有元素都出现3次,假设出现3次的元素有n个,这样的话假如我们统计所有元素的某一位(比如最后一位),其一共有3n+1个二进制位。因为对与同一个元素来说,其所有的二进制位一定是相同的,所以对这些元素的某一位来说一定是以3个1或3个0为单位出现的,即3n+1个二进制位中一定是3x个1和3y个0,其中x+y=n,再外加一个target对应的二进制位(1或0都有可能)。综上所述,我们可以统计所有数字每一位上1的个数,对3取模,如果为1就说明target对应位为1,否则为0。

  • 下面问题就是如何统计每一位上1的个数,一个比较好的方法就是采用位运算来处理,

//single number ii
class Solution_137 {
public:

    int singleNumber(int A[], int n) {
        int ret = 0;
        for (int i = 0; i < 32;i++)
        {
            int cnt = 0;
            for (int j = 0; j < n;j++)
            {
                cnt += (A[j] >> i) & 1;
            }
            ret += ((cnt % 3) << i);
        }
        return ret;
    }

    int singleNumber(vector<int>& nums) {
        //对每一位进行累加,对次数取模运算
        /* 把所有整数按照32位二进制进行每一位上的与1运算  结果为3n或3n+1;为3n+1的那些位就是只出现一次的数的二进制中1所在的位
        */
        int ret = 0;
        for (int i = 0; i < 32; i++)
        {
            int cnt = 0;//计每一位的1的个数
            for (int j = 0; j < nums.size();j++)
            {
                cnt += (nums[i] >> i) & 1; //0的不需要考虑
            }
            //把3n+1的那些位的1移回原位并累加起来 |=  也行  
            ret += (cnt % 3) << i;
        }
        return ret;
    }
};

题目来源

以上是关于137. Single Number II的主要内容,如果未能解决你的问题,请参考以下文章

137. Single Number II

137. Single Number II

137. Single Number II(js)

137. Single Number II

LeetCode136 Single Number, LeetCode137 Single Number II, LeetCode260 Single Number III

[leetcode-137-Single Number II]