找出一个数组唯一一个出现2次的数字

题目描述:一个N个元素的数组,存储1 - N-1的数字,其中只有一个数字重复出现,找出那个重复的数字;要求时间空间效率高。

这个题有个隐含的规律,所有的数字都是连续的,说明啥?可以求和啊!

于是解法一:先对N个元素求和为sum,设重复元素为a(1<=a<=N-1),那么sum也等于1+2+...+N-1 + a,欲求a,只需用sum一次减去1-N-1即可了:

int find(int * array,int len)
{
    if(array == NULL ) exit();
    int sum =0;
    int i;
    for(i=0;i<len;i++)
   {
       sum +=array[i];
    }
    for(i=1;i<len;i++)
    {
        sum -= i;
     }
     return sum;
}

该函数还可以优化:

int find(int * array,int len)
{
    if(array == NULL ) exit();
    int sum = 0;
    int i;
    for(i=0;i<len;i++)
   {
       sum += (array[i] - i);
    }
     return sum;
}
解法二:既然该函数只有一个重复出现,那么可不可以用异或呢,答案是肯定的,其实和求和的思想一样,先把数组元素异或,那么是不是就得到了剩下除去a的N-2个元素异或值,那么在一次异或1-N-1,是不是就把N-2个重复元素过滤掉了,就只剩下a了:

int find(int * array,int len)
{
    if(array == NULL ) exit();
    int xor =0;
    int i;
    for(i=0;i<len;i++)
   {
       xor ^= (array[i] ^ i);
    }
     return xor;
}

这样两个解法时间复杂度都是O(n),空间复杂度为O(1),应该算高效了!

欢迎大家补充其他想法,最好是时间复杂度都是O(n),空间复杂度为O(1)。谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值