题目

  1. (基础回顾)如何判断浮点数是否相等
  2. (拓展)有103个整数,其中有50个数出现了两次,3个数出现了一次 ,找出出现了一次的那三个数。

思路

(拓展)
(1)、由于知道三个数字只出现了一次,其他数字皆出现了两次,因此n(数组长度)一定为奇数;
(2)、3个只出现一次的数,他们的bit位肯定不可能完全相同,也就是说,虽然有些bit位上的数可能相等,但肯定至少存在某个bit位,在这3个数中,有两个数的该bit位为1,一个数的该bit位为0;或者两个数的该bit位为0,一个数的该bit位为1。
(3)、我们可以通过扫描int的所有bit位,扫描每个bit位时,遍历数组,如果能找出符合上面条件的,就可以找出其中一个只出现一次的数字,该数字与另外两个只出现一次的数字的bit位不同。(通过bit位不同可以分成两堆,对每堆进行异或,如果异或结果表明两堆结果都不为零,那么说明分开了,偶数个数的那堆有两个只出现一次的数,奇数个数的那堆有一个只出现一次的数)
(4)、分开剩下的那两个只出现一次的数则可以套用之前写过的那个函数即可。

代码

第一题

#include <stdio.h>
#include <stdlib.h>

//判断浮点数是否等于某个值
int main()
{
    float f=234.56;
    if(f-234.56 > -0.0001 && f-234.56 < 0.0001)
    {
        printf("f等于234.56\n");
    }else{
        printf("f不等于234.56\n");
    }
    system("pause");
}

第二题

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int xorArr(int *arr,int n)
{
    int i;
    int result;
    if(arr!=NULL && n>0)
    {
        result=0;
        for(i=0;i<n;i++)
        {
            result^=arr[i];
        }
        return result;
    }
}

//返回数字a的最低位的1,其他的位数都是0的一个数
int findFirstBit1Index(int a)
{
    return a&(-a);
}


//函数功能:找出一组数组中,两个只出现一次的数字
void findTwoNumInArrayOnlyOnce(int *arr,int n,int *second,int *third)
{
    int xorResult;
    int index;
    int i;
    if(arr == NULL || n<2)
    {
        return;
    }
    *second=0;
    *third=0;
    xorResult=xorArr(arr,n);//将arr中的所有数异或
    index=findFirstBit1Index(xorResult);//找到异或结果的为1的最低位数
    for(i=0;i<n;i++)
    {
        if(arr[i]&index)
        {
            *second^=arr[i];
        }else{
            *third^=arr[i];
        }
    }

}

void findThreeNumInArrayOnlyOnce(int *arr,int n,int *first,int *second,int *third)
{
    int countBit;
    int i,j;
    int count1,count0,temp1,temp0;
    if(arr == NULL || n<3)
    {
        return;
    }
    *first=0;
    *second=0;
    *third=0;
    //将全部数据分为两类,第一类bit=1,第二类bit=0
    countBit=sizeof(int)*8;//每一个int型的整数所占的bit数
    //count1和count0分别保存第一类和第零类中的元素个数
    //temp1和temp0分别保存第一类和第零类中,各自的所有元素的异或结果
    for(i=0;i<countBit;i++)
    {
        count1=count0=temp1=temp0=0;//每次循环清零
        for(j=0;j<n;j++)
        {
            if(arr[j]&(1<<i))//检测arr[j]在第i位是否为1
            {
                count1++;
                temp1^=arr[j];
            }else{
                count0++;
                temp0^=arr[j];
            }
        }
        if(count1%2)//count1为奇数时,有两种可能:
                        //(1)、有两个只出现一次的数的该bit位为0,一个只出现一次的数的该bit位为1;
                       //(2)、三个只出现一次的数的该bit位都是1
        {
            if(temp0!=0)//说明排除了第二种情况
            {
                *first=temp1;
                arr[n]=temp1;
                findTwoNumInArrayOnlyOnce(arr,n+1,second,third);
                return;
            }
        }else{//count1为偶数时,同样有两种可能性:
             //(1)、有两个只出现一次的数的该bit位为1,一个只出现一次的数的该bit位为0;
            //(2)、三个只出现一次的数的该bit位都是0
            if(temp1!=0)//说明排除了第二种情况
            {
                *first=temp0;
                arr[n]=temp0;
                findTwoNumInArrayOnlyOnce(arr,n+1,second,third);
                return;
            }

        }

    }

}


int main()
{
    int n,i;
    int *arr;
    int first,second,third;
    printf("请输入总共有多少个数:\n");
    while(scanf("%d",&n)!=EOF & n>0)
    {
        arr=(int *)malloc((n+1)*sizeof(int));//多开辟一个空间,将找到的第一个数
                                            //加入最后一个位置,使得这个数在数组中出现两次,
                                           //进而方便寻找后面两个只出现一次的数
        if(arr == NULL)
        {
            exit(EXIT_FAILURE);
        }
        printf("请输入分别有哪些数:\n");
        for(i=0;i<n;i++)
        {
            scanf("%d",&arr[i]);
        }
        findThreeNumInArrayOnlyOnce(arr,n,&first,&second,&third);
        printf("只出现一次的三个数分别是%d %d %d\n",first,second,third);
    }
    system("pause");
}

执行结果

第一题
图片说明

第二题

以9个为例,验证代码的可行性

图片说明