找出两个只出现一次的数

前言

周末和大学的几个伙计聚了一下,很开心,大家都很懂事而且都在努力,已经有两年硕士毕业去雅虎的,薪资待遇更是没得说,哈哈,聊得很开心,不过周末没怎么写代码,这里在九度oj水几道题,顺便记录一下(ps:貌似这个题目之前有记录过,不管了)

题目

题目描述:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
输入:
输入的第一行包括一个整数N(1<=N<=1000)。
接下来的一行包括N个整数。
输出:
可能有多组测试数据,对于每组数据,
找出这个数组中的两个只出现了一次的数字。
输出的数字的顺序为从小到大。
样例输入:
6
2 3 9 3 7 2 
样例输出:
7 9


思路

这里主要考察c的位运算,介绍两个异或运算的性质:
  • 任何一个数字异或它自己都等于0
  • 任何一个数字(除0外)异或0都等于它本身
所以我们可以考虑如下思路:
  • 从头到尾异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果
  • 由于两个数字肯定不一样,那么异或结果肯定不全为0,找出第一个为1的位置,记为loc
  • 通过判断数组每个数的loc位是否为1,将数组分为两部分
  • 两部分数组分别异或即可

ac代码

#include 
#include 
 
int firstone_loc(int num)
{
    int i;
    for (i = 0; num % 2 == 0; i ++) {
        num = num >> 1;
    }
 
    return i;
}
 
int judge_loc(int num, int loc)
{
    num = num >> loc;
    if (num % 2 == 1) {
        return 1;
    } else {
        return 0;
    }
}
 
int main(void)
{
    int i, n, unique, first, second, loc, flag, *arr;
 
    while (scanf("%d", &n) != EOF) {
        arr = (int *)malloc(sizeof(int) * n);
        for (i = unique = 0; i < n; i ++) {
            scanf("%d", arr + i);
            unique ^= arr[i]; 
        }
 
        // 第一个为1的位
        loc = firstone_loc(unique);
 
        for (i = first = second = 0; i < n; i ++) {
            flag = judge_loc(arr[i], loc);
            if (flag) {
                first ^= arr[i];
            } else {
                second ^= arr[i];
            }
        }
 
        if (first < second) {
            printf("%d %d\n", first, second);
        } else {
            printf("%d %d\n", second, first);
        }
 
        free(arr);
    }
 
    return 0;
}
/**************************************************************
    Problem: 1256
    User: wangzhengyi
    Language: C
    Result: Accepted
    Time:570 ms
    Memory:912 kb
****************************************************************/

这里需要提示一下,由于我本身对位运算也不够熟悉,因为我判断第i位是否为1,是用%2是否为1判断的,其实如果对位运算熟悉,直接&1即可

按照上述方法的ac代码

#include 
#include 
 
int firstone_loc(int num)
{
    int i;
    for (i = 0; (num & 1) == 0; i ++) {
        num = num >> 1;
    }
 
    return i;
}
 
int judge_loc(int num, int loc)
{
    num = num >> loc;
     
    return (num & 1);
}
 
int main(void)
{
    int i, n, unique, first, second, loc, flag, *arr;
 
    while (scanf("%d", &n) != EOF) {
        arr = (int *)malloc(sizeof(int) * n);
        for (i = unique = 0; i < n; i ++) {
            scanf("%d", arr + i);
            unique ^= arr[i]; 
        }
 
        // 第一个为1的位
        loc = firstone_loc(unique);
 
        for (i = first = second = 0; i < n; i ++) {
            flag = judge_loc(arr[i], loc);
            if (flag) {
                first ^= arr[i];
            } else {
                second ^= arr[i];
            }
        }
 
        if (first < second) {
            printf("%d %d\n", first, second);
        } else {
            printf("%d %d\n", second, first);
        }
 
        free(arr);
    }
 
    return 0;
}
 
/**************************************************************
    Problem: 1256
    User: wangzhengyi
    Language: C
    Result: Accepted
    Time:560 ms
    Memory:912 kb
****************************************************************/


对比



大家可以看到,明显位运算要比取余运算快10ms的时间

你可能感兴趣的:(C/C++,ACM)