leetcode 15 Single Number II

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?

对于”只有一个数出现一次,其余数出现2次“的情况,很简单,只要把数组中所有数异或一遍就是这个出现一次的数。

本题用一个大小为32的数组cnt来记录:(int数据的每个二进制位1的出现次数)%3,程序中cnt[i]记录第i+1个二进制位。如果某个数出现了三次并且他的第i+1个二进制位为1,因为做了模3操作,那么该数对数组cnt[i]的贡献为0,那么遍历完整个输入数组后,cnt[i]存储的就是这个出现一次的数的第i+1个二进制位。剩余的位就是只出现一次的那个数了。不过还要考虑正负号。

   对于数组中的负数,都取其绝对值,这对结果没有影响,只是cnt数组最后保存的是这个出现一次的数的绝对值的二进制位,因此同时还要通过记录原数据的符号位来确定这个只出现一次的数的正负。


#include<iostream>
#include<cstdio>
using namespace std;
#define N 1005
int singleNumber(int A[],int n)
{
        int countOne[32]={0},i;//cut[i]表示A中第(i+1)个二进制位的1个数(结果对3求模)
        int tmp,k;
        int sign=0;//用来确定single number的符号,0正1负
        for(i=0;i<n;i++)
        {
                tmp=A[i];
                if(A[i]<0)//将负数变为正数
                {
                        tmp*=-1;
                        sign=(sign+1)%3;//记录最高位为1还是为零
                }
                for(k=0;k<32;k++)//对全是正数进行处理
                {
                        countOne[k]=(countOne[k]+(tmp&0x00000001))%3;
                        tmp=tmp>>1;
                }
        }
        int res=0,base=1;
        for(i=0;i<32;i++)
        {
                res+=(base*countOne[i]);//将二进制数变为整数
                base<<=1;//权重
        }
        return sign==0?res:-1*res;//若为负数,则恢复为负数
}
int main(int argc,char *argv[])
{
        freopen("input.txt","r",stdin);
        int num,tmp,a[N],i;
        cin>>num;
        for(i=0;i<num;i++)
        {
                cin>>tmp;
                a[i]=tmp;
        }
        cout<<singleNumber(a,num)<<endl;
        return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值