137. Single Number II

113 篇文章 0 订阅

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

Note:

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

题目:其他数字都出现3此,除了有个数不是三次,找出那个数。

这道题目不会,只看得懂简单的做法。


我的答案:

看了思路一,自己写了个差不多思路的代码

int singleNumber(vector<int>& nums) {
        vector<int>vec(32,0);
        int res= 0;
        for(int j = 0; j < 32; j++){
            int count = 0;
            for(int i = 0; i <nums.size(); i++){
                if((nums[i]&(1<<j)) != 0)
                count++;
            }
            count %= 3;
            if(count != 0)
            res |= (1 << j);
        }
        return res;
    }

1.简单做法

将每个数字,转换为二进制,计算每位上出现的次数,再对这个次数取余。

int singleNumber(vector<int>A) {
    int n = A.size();
    int bitnum[32]={0};
    int res=0;
    for(int i=0; i<32; i++){
        for(int j=0; j<n; j++){
            bitnum[i]+=(A[j]>>i)&1;
        }
        res|=(bitnum[i]%3)<<i;
    }
    return res;
}
时间:O(32*N),这是一个通用的解法,如果把出现3次改为 k 次,那么只需模k就行了。



2.这种做法没看懂

貌似是有这么一张表

a b 用两位记录满3次的状态,c是输入的数字

public class Solution {

    public int singleNumber(int[] nums) {
        //we need to implement a tree-time counter(base 3) that if a bit appears three time ,it will be zero.
        //#curent  income  ouput
        //# ab      c/c       ab/ab
        //# 00      1/0       01/00
        //# 01      1/0       10/01
        //# 10      1/0       00/10
        // a=~abc+a~b~c;
        // b=~a~bc+~ab~c;
        int a=0;
        int b=0;
        for(int c:nums){
            int ta=(~a&b&c)|(a&~b&~c);
            b=(~a&~b&c)|(~a&b&~c);
            a=ta;
        }
        //we need find the number that is 01,10 => 1, 00 => 0.
        return a|b;

    }
}

3.这种我也看不懂

解释:

 这是一个更快一些的解法,利用三个变量分别保存各个二进制位上 1 出现一次、两次、三次的分布情况,最后只需返回变量一就行了。

每次循环先计算 twos,即出现两次的 1 的分布,然后计算出现一次的 1 的分布,接着 二者进行与操作得到出现三次的 1 的分布情况,然后对 threes 取反,再与 ones、twos进行与操作,这样的目的是将出现了三次的位置清零。

int singleNumber1(int A[], int n) {
    int one=0, two=0, three=0;
    for(int i=0; i<n; i++){
        two |= one&A[i];
        one^=A[i];
        //cout<<one<<endl;
        three=one&two;
        one&= ~three;
        two&= ~three;
    }
    return one;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值