找出两个只出现一次的数

来源:互联网 发布:mac os不支持银联 编辑:程序博客网 时间:2024/05/22 02:23

前言

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

题目

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


思路

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

ac代码

#include <stdio.h>#include <stdlib.h> 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 <stdio.h>#include <stdlib.h> 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的时间
原创粉丝点击