找出三个只出现一次的数字 C语言实现

题目:一个数组中有三个数字a、b、c只出现一次,其他数字都出现了两次。请找出三个只出现一次的数字。

分析:如果我们把数组中所有数字都异或起来,那最终的结果(记为x)就是a、b、c三个数字的异或结果(x=a^b^c)。其他出现了两次的数字在异或运算中相互抵消了。

我们可以证明异或的结果x不可能是a、b、c三个互不相同的数字中的任何一个。

由于x与a、b、c都各不相同,因此x^a、x^b、x^c都不等于0。

我们定义一个函数f(n),它的结果是保留数字n的二进制表示中的最后一位1,而把其他所有位都变成0。f(x^a)、f(x^b)、f(x^c)的结果均不等于0。

f(x^a)^f(x^b)^f(x^c)的结果的二进制中至少有一位是1。假设最后一位是1的位是第m位。那么x^a、x^b、x^c的结果中,有一个或者三个数字的第m位是1。

可以证明x^a、x^b、x^c的三个结果第m位不可能都是1。

因此x^a、x^b、x^c三个数字中,只有一个数字的第m位是1。于是我们找到了能够区分a、b、c三个数字的标准。这三个数字中,只有一个数字满足这个标准,而另外两个数字不满足。一旦这个满足标准数字找出来之后,另外两个数字也就可以找出来了。

#include<stdio.h>
static int lastBitOf1(int x)
{
    return x&-x;
}
static void getTwoUnique(int a[],int n,int b[])
{
    int xorResult=0;
    for(int i=0;i<n;++i)
        xorResult^=a[i];
    int diff=lastBitOf1(xorResult);
    int first=0;
    int second=0;
    for(int i=0;i<n;++i)
    {
        if(diff&a[i])
            first^=a[i];
        else
            second^=a[i];
    }
    b[1]=first;
    b[2]=second;
}
void getThreeUnique(int a[],int n,int b[])
{
    if(n<3)
        return ;
    int xorResult=0;
    for(int i=0;i<n;++i)
    {
        xorResult^=a[i];
    }
    int flags=0;
    for(int i=0;i<n;++i)
    {
        flags^=lastBitOf1(xorResult^a[i]);
    }
    flags=lastBitOf1(flags);
    int first=0;
    for(int i=0;i<n;++i)
    {
        if(flags==lastBitOf1(xorResult^a[i]))
        {
            first^=a[i];
        }
    }
    b[0]=first;
    for(int i=0;i<n;++i)
    {
        if(a[i]==first)
        {
            int t=a[i];
            a[i]=a[n-1];//数组的最后一个元素
            a[n-1]=t;
            break;
        }
    }
    getTwoUnique(a,n-1,b);
}
int main(int argc, char *argv[])
{
    int a[]={2,2,3,3,4,4,  5,6,7,  8,8};
    int b[3];
    getThreeUnique(a,11,b);
    for(int i=0;i<3;++i){
        printf("%d",b[i]);
        if(i+1!=3)
            printf(" ");
    }
    printf("\n");
    return 0;
}

结果是正确的

时间: 2024-07-31 03:20:20

找出三个只出现一次的数字 C语言实现的相关文章

【转】一个数组中有三个数字a、b、c只出现一次,其他数字都出现了两次。请找出三个只出现一次的数字。

转自:http://zhedahht.blog.163.com/ 题目:一个数组中有三个数字a.b.c只出现一次,其他数字都出现了两次.请找出三个只出现一次的数字. 分析:在博客http://zhedahht.blog.163.com/blog/static/2541117420071128950682/中我们讨论了如何在一个数组中找出两个只出现一次的数字.在这道题中,如果我们能够找出一个只出现一次的数字,剩下两个只出现一次的数字就很容易找出来了. 如果我们把数组中所有数字都异或起来,那最终的结

40 - 找出数组中只出现一次的数字

题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.编写程序找出这个两个只出现一次的数字.要求时间复杂度O(n),空间复杂度O(1). 如 {2,4,3,6,3,2,5,5},输出{4,6} 解析: 空间复杂度为O(1)断绝了用hash-table的思路,时间复杂度O(n)断绝排序的思路. 如何判断一个数字出现2次呢? 计数 异或:如果出现2次,任意数字和自己异或都为0 异或的性质: 任何数字和 0 异或,都为它本身. 任意数字和自己异或都为0. 由于成对出现的元素异或结果为 0

找出数组中只出现一次的数字

题目 : 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 解析 首先:位运算中异或的性质:两个相同数字异或=0,一个数和0异或还是它本身.异或运算满足交换律结合律. 当只有一个数出现一次时,我们把数组中所有的数,依次异或运算,最后剩下的就是落单的数,因为成对儿出现的都抵消了. 依照这个思路,我们来看两个数(我们假设是AB)出现一次的数组.我们首先还是先异或,剩下的数字肯定是A.B异或的结果,这个结果的二进制中的1,表现的是A和B的不同的位.我们就取第

面试题:找出数组中只出现一次的数字(二)

难度:中等 一个整数数组,除了一个数之外所有数字都出现了3次,找出这个数字来. 注意: 你的算法应该是线性运行复杂度,且不能使用额外内存空间. 答案: public class Solution { public int singleNumber(int[] nums) { int ones = 0, twos = 0, threes = 0; for (int i = 0; i < nums.length; i++) { // twos holds the num that appears t

面试题:找出数组中只出现一次的数字

难度:中等 一个整数数组,除了一个数之外所有数字都出现了2次,找出这个数字来. 注意: 你的算法应该是线性运行复杂度,且不能使用额外内存空间. 答案: public class Solution { public int singleNumber(int[] nums) { int n =0; // as we know that bitwise XOR in Java // 0 ^ N = N // N ^ N = 0 for(int i=0; i!=nums.length; i++) { n

面试题1:找出一个数组中三个只出现一次的数字

version1: 找出一个数组中一个只出现一次的数字,其他数字都出现两次:将所有数字异或,得到的结果即为只出现一次的. version2: 找出一个数组中两个只出现一次的数字,其他数字都出现两次:将所有数字异或,得到的结果即为x=a^b, index为x中第一个为1的位,则a 和b中第index为必然有一个为1,有一个为0.据此将所有数据分为两组,一组的第index为都为1,另一组第index为都为0,第一组数字异或得到a,第二组数字异或得到b. 时间复杂度为o(n),空间复杂度为o(1).

【c语言】第一个只出现一次的字符题目:在字符串中找出第一个只出现一次的字符

// 第一个只出现一次的字符题目:在字符串中找出第一个只出现一次的字符. // 如输入"abaccdeff",则输出'b'. #include <stdio.h> #include <string.h> char find_one(char *str) { int a[256]; int len = strlen(str); int i = 0; memset(a, 0, sizeof(a)); for (i = 0; i<len; i++) { a[st

在字符串中找出第一个只出现一次的字符

题目: 在字符串中找出第一个只出现一次的字符.如输入"abaccdeff",则输出'b'. 题目分析: 对于在字符串中找出第一个出现一次的字符,联系ASCII码表,能够得到有256中不同的字符,可以利用字符的编码,将每个字符的编码作为数组的下表,建立一个有256个元素的数组arr[256],将数组中的每一个元素对应统计字符的个数,从字符串的第一个字符进行遍历,遇到一个字符给对应的数组元素加1,当数组中的其中一个元素变到2,则输出这个元素所对应的数组下表,即就是这个字符的ASCII码.

在字符串中找出第一个只出现一次的字符。 如输入“abaccdeff”,则输出&#39;b&#39;。

在字符串中找出第一个只出现一次的字符. 如输入"abaccdeff",则输出'b'. 这个题加一些要求维度只能为n 代码如下: #include <stdio.h> #include <assert.h> char FLetter(char arry[],int len) {              int letterNumber[256] = {0};              int i = 0;              char *ch  = arr