zoukankan      html  css  js  c++  java
  • 剑指offer面试题40:数组中只出现一次的数字

    问题:一个整型数组中除了两个数字之外,其他的数字都出现了两次,写出程序找出这两个只出现了一次的数字,时间复杂度要求O(n),空间复杂度要求O(1).

    一看到这个题想到了很多“可能”的解法,很飘散的思绪,比如什么哈希啊,什么加A再减去A,剩下的就是单独的了啊,都是写没啥用的解法。

    后面看到了书上的解法,觉得很巧妙,于是贴了上来,顺便标明了自己当时不是很清楚的理解。

     书上说这道题很难,我觉得算法这种东西,本质上并没有难一说,而是主张一个“巧妙”,九拐十八弯。

     从易入难,举一反三是算法学习中必不可少的一种经历。

    闲话少说,言归正传,首先这个题目是要求我们找出数组中的两个分别出现了一次的数字,而且时间复杂度要求O(n),如果说我们想靠找到数组中的一个A再在后面找到另一个A,这样的话,时间复杂度完全不符合要求,相应的时间复杂度为O(n^2),太。。。。慢了。。

    那么怎样才能解决这个问题呢?

    根据书上的提示,我们先来考虑一个比较 简单的场景,即数组中只有一个单独的不成对的数,我们可以通过连续对数组中的元素求异或(“^”操作),因为A和A的异或结果是为零的,根据这个思想,我们可以把异或的结果保存到一个result变量里,到最后这个变量的结果就是我们所求的那个单独的数。(当时困扰楼主了一会儿,让lz感觉到莫名其妙的是书上的”依次异或“这句话,楼主心想,依次异或,难不成还是依次便利数组中的元素,求异或?这样的复杂度还是O(n^2),太诡异了,现在才发现自己当时的想法是错误的,曲解了作者的想法,希望有这么理解的同学不要再这么想了~)

    接下来考虑数组中拥有两个独立数据的情况,对这个数组中的元素同样进行上述的异或操作,得到的最终结果是两个不同的数的异或结果,由于两个数不相同,那么这个结果中肯定不为零,也就是存在1的位数,我们可以根据此结果把这个数组分成两个子数组,从低到高位,第一个1出现的位数为1的数和这位为0的数为两个数组,那么肯定的是,这两个单独的数分别被分到了两个子数组里,那么就好办了,对这两个子数组的元素分别进行异或操作,得到的就是这两个单独的数。

    根据此思路完成的代码如下:

     1 #include<iostream>
     2 using namespace std;
     3 
     4 void find_two_aloneC(int a[],int length)
     5 {
     6     int i,j=1,Xor=0,Xor_0=0,Xor_1=0;
     7     
     8     for(i =0;i<length;i++)
     9         Xor = Xor^a[i];
    10     while(((Xor & 1) == 0))
    11     {
    12         Xor = (Xor >> 1);
    13         j = j << 1;
    14     }
    15     for(i = 0;i<length;i++)
    16     {
    17         if((a[i] & j) == 0)
    18         {
    19             Xor_0 = Xor_0^a[i];
    20         }
    21         else if((a[i] & j )!=0)
    22         {
    23             Xor_1 = Xor_1^a[i];
    24         }
    25     }
    26     cout << Xor_0 << endl;
    27     cout << Xor_1 << endl;
    28 }
    29 int main()
    30 {
    31     int a[] = {2,3,4,5,3,3,3,5,2,5};
    32     find_two_aloneC(a,10);
    33     system("pause");
    34     
    35     return 0;
    36 }
  • 相关阅读:
    Leetcode 15 3Sum
    Leetcode 383 Ransom Note
    用i个点组成高度为不超过j的二叉树的数量。
    配对问题 小于10 1.3.5
    字符矩阵的旋转 镜面对称 1.2.2
    字符串统计 连续的某个字符的数量 1.1.4
    USACO twofive 没理解
    1002 All Roads Lead to Rome
    USACO 5.5.1 求矩形并的周长
    USACO 5.5.2 字符串的最小表示法
  • 原文地址:https://www.cnblogs.com/xiawen/p/3023832.html
Copyright © 2011-2022 走看看