zoukankan      html  css  js  c++  java
  • 二进制和位运算中的异或

    1、给出一个问题:给你一个整形数组,这个数组中除了一个数字仅仅出现一次外,其它数字都仅仅出现两次,求出那个仅仅出现一次的数字?

    要求:时间复杂度为O(n) , 空间复杂度为O(1)。


    这个题目的难点在于空间复杂度的限制。


    解法:一个数出现两个,两个数同样。而相等两个数异或的值为0 。 所以。我们仅仅须要把整个数组的数都异或一遍,我们就能得到仅仅出现了一次的那个数字


    <span style="font-size:18px;">int get_one_num(int num[] , int n)
    {
        int first = num[0] , i;
        for(i = 1; i < n; i++)
            first ^= num[i];
        return first;
    }</span>


    2、问题二:如今这个数组中,有两个数仅仅出现了一次。求出这两个数字,且时间、空间复杂度不变。


    假设依据第一个问题的解法。我们最后面也是得到了一个值,但这个值是那两个数字(仅仅出现一次)的异或值。我们又不知道这个两个数字的不论什么一个。所以我们得不到这两个数字。


    假设我们把数组切割成2个数组。每一个数组中仅仅含有一个仅仅出现一次的数字。再调用问题一的解法,我们就能得到结果。

    关键在于我们怎么来切割这个数组,且空间复杂度是O(1)?

    首先我们从头到尾依次异或数组中的每个数字,得到的结果就是两个仅仅出现一次数字的异或结果,由于这两个数字肯定不一样,所以得到的结果数字肯定不是0。也就是这个二进制数字钟至少有一位是1 。 我们在这个结果数字中华找到第一个为 1的位的位置,记为第n为。我们就通过第n位是不是1,一把这个数组切割成一个数组。


    代码

    <span style="font-size:18px;">int find_one(int x)
    {
        int p = 1;
        while(true)
        {
            if((p^x) < x)  break;
            p <<= 1;
        }
        return p;
    }
    
    void get_one_num(int num , int n)
    {
        int first = num[0] , i;
        for(i = 1; i < n; i++)
            first ^= num[i];
        int one = find_one(first);
    
        int x = 0 , y = 0;
        for(i = 0; i < n; i++)
        {
            if((one^num[i]) < num[i])
                x ^= num[i];
            else y ^= num[i];
        }
    
        cout<<(x<y?x:y)<<" "<<(x>y?x:y)<<endl;
    }</span>



  • 相关阅读:
    认识弹性盒子
    管理Linux服务器的用户和组(续篇)
    管理Linux服务器的用户和组
    centos7 mysql数据库安装和配置
    熟练使用Linux进程管理类命令
    熟练使用Linux系统信息类命令
    Linux操作系统-基本命令(二)
    Linux操作系统-基本命令(一)
    api接口统一封装
    10分钟,让你彻底明白Promise原理
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/6797296.html
Copyright © 2011-2022 走看看