zoukankan      html  css  js  c++  java
  • 由n个元素组成的数组,n-2个数出现了偶数次,两个数出现了奇数次,且这两个数不相等,如何用O(1)的空间复杂度,找出这两个数

    思路分析:

        方法一:涉及到两个数,就要用到异或定理了:若a^b=x,则a=b^x,b=x^a。对于这道题,假设这两个数分别为a、b,将数组中所有元素异或之后结果为x,因为a!=b,所以x=a^b,且x!=0,判断x中位为1的位数,只需要知道某一个位为1的位数k,如00101100,k可以取2或者3,或者5.因为x中第k位为1表示a或b中有一个数的第k位也为1,假设为a,将x与数组中第k位为1的数进行异或时,也即将x与a以及其他第k位为1的出现过偶数次的数进行异或,化简即为x与a异或,最终结果即为b。

    程序示例如下:

    #include "stdafx.h"
    #include <stdio.h>
    void FindElement(int a[], int length)
    {
        if (a == NULL || length <= 0)
            printf("数组中无元素,找个毛啊。");
        else
        {
            int s = 0;
            int i;
            int k = 0;
            for (i = 0; i < length; i++)
            {
                s = s^a[i];
            }
            int s1 = s;
            int s2 = s;
            while (!(s1 & 1))
            {
                s1 = s1 >> 1;
                k++;
            }
            for (i = 0; i < length; i++)
            {
                if ((a[i] >> k) & 1)
                    s = s^a[i];            
            }
            printf("%d %d
    ", s, s^s2);
        }    
    }
    int main()
    {
        int array[] = { 1, 2, 2, 3, 3, 4, 1, 5 };
        int len = sizeof(array) / sizeof(array[0]);
        FindElement(array, len);
        getchar();
        return 0;
    }

        效果如图:

        方法二:如果能够把原数组分为两个子数组,在每个子数组中,包含一个只出现一次的数字,而其他数字都出现两次,问题就可以很容易的解决了:分别对两个子数组执行异或运算。

    首先从头到尾依次异或数组中的每一个数字,因为其他数字都出现了两次,在疑惑中全部抵消掉了,所以最终得到的结果将是两个只出现一次的数字的异或结果。而这两个数字肯定不一样,那么这个异或结果肯定不为0,也就是说在这个结果数字的二进制表示中至少就有一位为1,否则就为0了。在结果数字中找到第一个为1的位的位置,记为第N位,那么这两个数字一个第N位为1,另一个第N位为0,这样异或后结果数字的第N位才能为1.此时以第N位是不是1为标准把原数组中的数字分为两个子数组,第一个子数组中每个数字的第N位都为1,而第二个子数组的每个数字的第N位都为0.通过这种方法就可以把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其他数字都出现了两次。

    代码如下:

    #include "stdafx.h"
    #include <stdio.h>
    void findOnce(int data[], int n, int &num1, int &num2)
    {
        if (n < 5)
            return;
        int r1 = 0;
        for (int i = 0; i < n; i++)
            r1 = r1^data[i];
        int bitNum = 0;
        while (!(r1 & 0x1))
        {
            r1 = r1 >> 1;
            bitNum++;
        }
        int flag = (1 << bitNum);
        num1 = 0;
        num2 = 0;
        for (int j = 0; j < n; j++)
        {
            if (data[j] & flag)
                num1 = num1^data[j];
            else
                num2 = num2^data[j];
        }
    }
    int main()
    {
        int array[] = { 1, 2, 3, 2, 4, 3, 5, 1 };
        int num1, num2;
        findOnce(array, sizeof(array) / sizeof(array[0]), num1, num2);
        printf("%d
    %d
    ", num1, num2);
        getchar();
        return 0;
    }

        效果如图:

  • 相关阅读:
    springboot项目前端页面中文搜索时,数据库查询为空(mysql)
    Eclipse修改项目包名
    eclipse中maven父子项目层级显示设置
    springboot整合pagehelper实现分页
    eclipse设置文档注释
    永久修改mysql时区
    前端页面展示时间与数据库时间相差8小时(mysql)
    前端页面展示时间与数据库时间相差5小时(mysql)
    AxureRP 9安装、激活、汉化
    PowerDesigner 16.5安装、激活
  • 原文地址:https://www.cnblogs.com/cysolo/p/3600088.html
Copyright © 2011-2022 走看看