• 由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;
    }

        效果如图:

  • 相关阅读:
    hdu 2019 数列有序!
    hdu 2023 求平均成绩
    HDU 5805 NanoApe Loves Sequence (思维题) BestCoder Round #86 1002
    51nod 1264 线段相交
    Gym 100801A Alex Origami Squares (求正方形边长)
    HDU 5512 Pagodas (gcd)
    HDU 5510 Bazinga (字符串匹配)
    UVALive 7269 Snake Carpet (构造)
    UVALive 7270 Osu! Master (阅读理解题)
    UVALive 7267 Mysterious Antiques in Sackler Museum (判断长方形)
  • 原文地址:https://www.cnblogs.com/cysolo/p/3600088.html
Copyright © 2020-2023  润新知