剑指offer之数组中只出现一次的数字

原创 2018年04月17日 18:43:38

题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

解题思路

方法一:异或

除了有两个数字只出现了一次,其他数字都出现了两次。异或运算中,任何一个数字和自己本身异或都是0,任何一个数字和0异或都是本身。

如果尝试把原数组分成两个子数组,且刚好每个子数组中各自包含一个只出现一次的数字。则在该前提下,每个子数组中,只有一个数字出现了一次,其他数字都出现了两次。

针对每个子数组,从头到尾依次异或每个数字,则最后留下来的就是只出现了一次的数字。因为出现两次的都抵消掉了。

怎样实现子数组的划分呢。若对原数组从头到尾的进行异或,则最后得到的结果就是两个只出现一次的数字的异或运算结果。这个结果的二进制表示中,至少有一位为1,因为这两个数不相同。该位记为从最低位开始计数的第n位。

则分组的标准定为从最低位开始计数的第n位是否为1。因为出现两次的同一个数字,各个位数上都是相同的,所以一定被分到同一个子数组中,且每个子数组中只包含一个出现一次的数字。

例如:数组元素为2,4,3,6,3,2,5,5,异或的结果为0010,也就是倒数第二位为1,也就是倒数第二位为标记位来进行拆分,那么第一个子数组就为{2,3,6,3,2},他们的倒数第二位为1,第二个子数组为{4,5,5}倒数第二位为0,对这两个子数组分别再异或,最终找到6和4。

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        //异或
        if(data.size() < 2) 
            return;
        int temp = data[0];
        for(int i = 1;i < data.size();i++) //先求出全部数的异或结果
            temp ^= data[i];
        if(temp == 0) //异或结果为0,说明没有两个只出现一次的不同的数字
            return;
        int index = 0;  //index为异或结果中1所在的最低位
        while((temp&1)==0){
            temp >>= 1;
            ++index;
        }
        *num1 = *num2 =0;
        for(int i=0;i<data.size();i++){ 
            if((data[i]>>index)&1) //表示每个数在标记index的地方为1
                *num1 ^= data[i];
            else                   //表示每个数在标记index的地方为0
                *num2 ^= data[i];
        }
    }
};

方法二:哈希表

用STL中的unorder_map存储,key为数组中每个数,value为其出现的次数,最后出现次数为1的,就是结果

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        //哈希表
        unordered_map<int, int> map;
        for(int i = 0; i < data.size(); i++)
            map[data[i]]++;
        vector<int> v;
        for(int i = 0; i < data.size(); i++)
            if(map[data[i]]== 1)
                v.push_back(data[i]);
        *num1 = v[0]; 
        *num2 = v[1];
    }
};

方法三:

遍历数组,使用一个ArrayList记录当前只出现了一次的值。
若当前遍历的值,在ArrayList中已经出现,则移除该值,继续遍历。
最后剩下的两个值,即为所求。

public class Solution {
        public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
                ArrayList<Integer>list=new ArrayList<Integer>();
                for(int i=0;i<array.length;i++)
                    {
                        if(!list.contains(array[i]))
                            list.add(array[i]);
                        else
                            list.remove(new Integer(array[i]));
                    }
                if(list.size()>1)
                    {
                        num1[0]=list.get(0);
                        num2[0]=list.get(1);
                    }
        }
}

方法四:暴力解法

对数组进行排序。
遍历一次数组,将array[i]分别与array[i-1]和array[i+1]作比较,若都不相同,则找到只出现一次的值。
注意处理第一个数字和最后一个数字的边界情况。

public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {

        ArrayList<Integer> arr = new ArrayList<Integer>();
        Arrays.sort(array);
        for(int i=0, len=array.length; i<len; i++){
            if(i==len-1 && array[i]!=array[i-1]){
                arr.add(array[i]);
            }else if(i==0 && array[i]!=array[i+1]){
                arr.add(array[i]);
            }else{
                if(i!=0 && i!=len-1 && array[i]!=array[i-1] && array[i]!=array[i+1]){
                    arr.add(array[i]);
                }
            }
        }
        num1[0] = arr.get(0);
        num2[0] = arr.get(1);
    }
}

剑指offer面试题40-数组中只出现一次的数字

题目: 一个整形数组里除了两个数字意外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 要求时间复杂度是On,空间复杂度为O1 这个是上一篇 2016阿里巴巴java笔试题 的...
  • q291611265
  • q291611265
  • 2015-08-31 13:51:26
  • 1431

剑指offer:数组中只出现一次的数字(java)

题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请些程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度为O(1).     如输入数组{2,4,3,6,3,2,5,...
  • abc7845129630
  • abc7845129630
  • 2016-10-06 19:03:31
  • 1361

剑指Offer面试题40(Java版):数组出现一次的数字

题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。  * 请些程序找出这两个只出现一次的数字。要求时间复杂度为O(n),空间复杂度为O(1) 例如输入数组{2,4,3,6,3,2,5,...
  • jsqfengbao
  • jsqfengbao
  • 2015-08-10 19:04:19
  • 1850

【剑指offer】数组中只出现一次的数字(1)

思路:上篇博文中已经了解到异或去重的原理,而且知道如果只有一个只出现一次的数字的求法,但这里是有两个只出现一次的数字,我们便要想办法把他分为两个子数组,每个子数组中包含一个只出现一次的数字,其他的数字...
  • mmc_maodun
  • mmc_maodun
  • 2014-05-31 08:59:12
  • 4144

牛客网剑指offer-数组中只出现一次的数字

题目描述一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。class Solution { public: //利用位运算的巧妙方法 void...
  • yhn19951008
  • yhn19951008
  • 2018-02-28 23:02:19
  • 10

《剑指Offer》面试题:数组中只出现一次的数字

题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。思路 根据异或去重的原理,我们知道如果只有一个只出现一次的数字的求法,但这里是有两个只出现...
  • u010412719
  • u010412719
  • 2015-10-12 21:35:32
  • 798

《剑指Offer》面试题:找出数组中有3个出现一次的数字

题目 一个int数组中有三个数字a、b、c只出现一次,其他数字都出现了两次。请找出三个只出现一次的数字。 思路 由于3个数字出现一次,其他数字均出现两次,因此可以得到n一定为奇数。 3个只出现...
  • u010412719
  • u010412719
  • 2015-10-13 21:09:24
  • 1349

码农小汪剑指Offer之38-数组中只出现一次的数字 异或运算的运用

题目描述一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。解题思路这道题,看上去没啥的,其实真实的很难,如果你从未接触过,一般情况下多数都是无法搞定这个问题的...
  • u012881904
  • u012881904
  • 2016-04-09 23:02:51
  • 335

【位运算】找出数组中,只出现一次的两个数字

题目: 一个整型数组里除了两个数字之外,其他的数字都出现了两次,请写程序找出这两个出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1). 分析: 由于限制了复杂度,所以要用异或...
  • wbb_1216
  • wbb_1216
  • 2017-03-21 10:29:37
  • 450

[Python]数组中只出现一次的数字

题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 解法1: 通过遍历把统计的数字次数存入python内置的字典dict,然后再搜寻出现一次...
  • jiayk2016
  • jiayk2016
  • 2018-03-16 11:11:17
  • 108
收藏助手
不良信息举报
您举报文章:剑指offer之数组中只出现一次的数字
举报原因:
原因补充:

(最多只允许输入30个字)