ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

C语言实现一个int类型数组里除了两个数字之外,其他的数字都出现了两次,找出这两个数字

2019-09-07 15:55:15  阅读:118  来源: 互联网

标签:arr 数字 int C语言 异或 数组 num1


题目是这样叙述的:
在一个数组中除两个数字只出现1次外,其它数字都出现了2次, 要求尽快找出这两个数字。

要求:时间复杂度为O(N),空间复杂度为O(1)。

请看我的分析:
将这道题简单化:
一个数组中只有一个数字出现一次,其他数字都是成对出现的,这时我们可以根据异或运算符的特性:A^B^A = B; 0 ^ A = A;我们可以将这个数组的全部元素依次做异或运算,最终结果就是那个只出现一次的数字。
不会的可看本人(2019-04-04)那天的博客

如果这个数组中出现两个不同的数字,而其他数字均出现两次,假设这两个数字分别是x, y。那如果可以将x, y分离到两个数组。这时这道题就变成两个我们简化之后的版本中的数组了。这样问题就可以得到解决了。由于x,y肯定是不相等的,因此在二进制上必定至少有一位是不同的。根据这一位是0还是1可以将x,y分开到A组和B组。并且数组中其他元素也可以根据这个方法划分到两个数组中。这时将两个数组分别做异或运算,结果就是这两个数字。
#include<stdio.h>

#define SIZE(arr) sizeof(arr)/sizeof(arr[0])

void find_num(int *arr, int len,int *num1,int *num2)
{
    int i;
    int sum = 0;
    for (i = 0; i < len; i++)
    {
        sum^=*(arr + i);//异或出所有数字
    }
    int j;
    for (j = 0; j < sizeof(int)* 8; j++)//int类型数组的字节数32
    {
        if (((sum >> j) & 1) == 1)//说明sum在右移 j 个单位后,二进制不一样
        {
            break;
        }
    }
    for (i = 0; i < len; i++)
    {
        if (((*(arr + i) >> j) & 1) == 1)
        {
            *num1 ^= (*(arr + i));//异或 j 位置为1的一组数字
        }
        else
        {
            *num2 ^= (*(arr + i));//异或 j 位置为0的一组数字
        }
    }
}

int main()
{
    int arr[] = { 1, 3, 5, 7, 1, 3, 5, 9 };
    int num1=0, num2=0;
    find_num(arr,SIZE(arr),&num1,&num2);
    printf("%d %d", num1, num2);
    return 0;
}

总结:复杂问题简单化,把两个出现一次的数字分割为两组出现一次的数组

标签:arr,数字,int,C语言,异或,数组,num1
来源: https://blog.51cto.com/14233078/2436437

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有