码迷,mamicode.com
首页 > 其他好文 > 详细

[LeetCode] 137. Single Number II (位运算)

时间:2017-08-19 18:31:28      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:problem   note   with   linear   有一个   problems   one   single   时间复杂度   

传送门

Description

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?

思路

题意:给定一个数组,其中有一个数出现一次,其他数出现三次,要求在时间复杂度为O(n)空间复杂度为O(1)的条件下,找出这个出现一次的数。

题解:

方法一:因为除了一个数外,其他每个数都出现三次,因此枚举每一位二进制位,统计每一位上这些数为1的数总共有多少个,然后与3相模,如果余1,证明这个出现一次的数的二进制在这位上为1。(此法是通用方法,适用于除一个数外,其他数出现k次,那么只需模k即可)

class Solution {
public:
    //12ms
    int singleNumber(vector<int>& nums) {
        int res = 0;
        for (int i = 0;i < 32;i++){
            int cnt = 0;
            int mask = 1 << i;
            for (int j = 0;j < nums.size();j++){
                if (nums[j] & mask){
                    cnt++;
                }
            }
            if (cnt % 3){
                res |= mask;
            }
        }
        return res;
    }
};

  

方法二:用两个变量记录所有数二进制位中哪些位为1出现一次,哪些二进制位为1出现两次,之所以只需两个,是因为同一个数最多只出现三次,因此我们可以选定状态 00 -> 01 -> 10来记录,那么我们用ones表示哪些位为1出现一次(模3后出现一次),用twos表示哪些位为1出现两次(模3后出现一次),当ones和twos某一二进制位上同时为1说明这位为1出现了三次,那么我们此时将ones和twos的这位二进制位清0,最后ones就是答案。

class Solution {
public:
    //9ms
    int singleNumber(vector<int>& nums) {
        int ones = 0,twos = 0,threes = 0;
        for (unsigned int i = 0;i < nums.size();i++){
            //以下两句代码不能颠倒次序,如若颠倒,则一个数先记录于ones,
            //然后twos的值依赖于ones及这个数,那么这个数就被统计了两次
            twos |= (nums[i] & ones);  //记录有哪些为进制位为1且出现两次存于twos
            ones ^= nums[i];           //记录有哪些二进制位为1且出现一次存于ones

            //以下三句是清零操作
            threes = ones & twos;
            ones &= ~threes;
            twos &= ~threes;
        }
        return ones;
    }
};

 

另外,方法二代码可精简如下:ones与twos的含义与上述相同。

class Solution {
public:
    //9ms
    int singleNumber(vector<int>& nums) {
        int ones = 0,twos = 0;
        for (unsigned int i = 0;i < nums.size();i++){
            //ones&~twos以及twos&~ones都是为了清零操作,两者二进制位都为1时清零
            ones = (ones ^ nums[i]) & (~twos);
            twos = (twos ^ nums[i]) & (~ones);
        }
        return ones;
    }
};

  

[LeetCode] 137. Single Number II (位运算)

标签:problem   note   with   linear   有一个   problems   one   single   时间复杂度   

原文地址:http://www.cnblogs.com/zzy19961112/p/7397289.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!