• C语言经典习题(异或思想)


    问题描述:

    一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。请找出这两个数
    例如:1 2 3 4 5 6 1 2 3 4  -> 5 6

    解题思路:主要用异或的思想

    预备知识:

    (1)两个相同的数异或的结果是0;
    (2)所有不为0的数和0异或的结果是本身。

    有了以上的了解,可以将数组的元素分成两组,按照这样的原则:

    • 要找的两个数分到不同的组
    • 相同的数要分到同一个组内

    比如:1 1 2 2 3 3 6, 4 4 5
    分成这样的两个组之后,每个组的元素异或的结果便是要找的两个元素。

    那么,如何进行分组呢?下面为具体步骤:
    为了方便理解,写出1-6的二进制序列:

    1 -> 0012 -> 010
    3 -> 0114 -> 100
    5 -> 1016 -> 110
    1. 第一步:将所有元素异或,得到即为5异或6的结果ret,也就是ret = 011
    2. 第二步:ret二进制序列中为1的位,则是5和6在该位上不一样,那么可以按照这个位来分组(比如011的第1个二进制位为1,5(101)和6(110)的第一位确实不相同)
    3. 第三步:分组,二进制位第1位为0的数有:2(010),4(100),6(110);二进制位第1位为1的数有:1(001),3(011),5(101)

    代码实现:

    1. void Find(int arr[], int sz, int *px, int* py)
    2. {
    3. int i = 0;int ret = 0;int pos; int num1,num2;
    4. //1. 要把所有数字异或
    5. for (i = 0; i < sz; i++){
    6. ret ^= arr[i];
    7. }
    8. //2. 计算ret的哪一位为1
    9. pos = 0;
    10. for (i = 0; i < 32; i++){
    11. if (((ret >> i) & 1) == 1){
    12. pos = i;
    13. break;}
    14. }
    15. //3. 把从低位向高的第pos位为1的数放在一个组,为0的放在另外一个组。
    16. num1 = 0; num2 = 0;
    17. for (i = 0; i < sz; i++){
    18. if (((arr[i] >> pos) & 1) == 1)
    19. num1 ^= arr[i];
    20. else
    21. num2 ^= arr[i];
    22. }
    23. *px = num1;*py = num2;
    24. }
    25. int main()
    26. {
    27. int arr[] = { 1,2,3,4,5,6,1,2,3,4 };
    28. int sz = sizeof(arr) / sizeof(arr[0]);
    29. int x = 0, y = 0;//输出型参数
    30. Find(arr, sz, &x, &y);
    31. printf("%d %d\n", x, y);
    32. return 0;
    33. }
  • 相关阅读:
    Linux课程四课---Linux开发环境的使用(gcc/g++编译器的相关)
    C++11重写muduo网络库——预备知识
    微信个人号如何实现自动回复呢?
    网络编程概述及Http协议
    【LeetCode】235.二叉搜索树的最近公共祖先
    STL priority_queue
    一个失败的案例
    【Python】(9)容器类型:集合(性质、添加、删除、运算)
    华为 ia综合topo
    【深入浅出 Yarn 架构与实现】2-1 Yarn 基础库概述
  • 原文地址:https://blog.csdn.net/m0_60416282/article/details/125548162