zoukankan      html  css  js  c++  java
  • bitmap以及异或运算法

    有40亿个整数,再给一个新的整数,需要判断新的整数是否在1亿个整数中。

    此处需要用到bitmap方法,每个整数用一个bit表示,1表示存在,0表示不存在。因此一个4字节的int=32个bit也就是可以表示32个数字,那么1亿个数字需要 100000000/32个int型。也就是需要申请100000000/32个字节的数组。需要耗费25M的内存。

    这种方法也降低了数组需要的内存。

    申请数组,N代表多少个数字,WORD代表一个int字节能表示多少位数字

    #define WORD 32

    #define SHIFT 5

    #define MASK 0x1f

    #define N 100000000

    int bitmap[1 + N / WORD];

    整型数组全部初始化为0.

    void init_bitmap()

    {

        int size;

        size = 1 + N / WORD;

        memset(bitmap, 0, size);

    }

    将数字对应的Bit置为1。对于号码 89256,由于89256 mod 32=2789…8,这样我们应该置a[2789]中32位字符串的第8位(从低位数起)为1。SHIFT在这里表示右移的个数,i>>SHIFT就等于89256 mod 32=2789. MASK也就是16进制的31. i & MASK就等于i/32(求余操作)

    void set(i)

    {

        bitmap[i >> SHIFT] |= (1<< (i & MASK));

    }

    判断是否存在,和前面用到的方法一样,不同的是这里运用的是与运算

    int Judge_exist(i)

    {

        return bitmap[i >> SHIFT] & (1 << (i & MASK));

    }

    将对应的数代表的bit位清零

    void clear(i)

    {

        bitmap[i >> SHIFT] &= ~(1 << (i & MASK));

    }

    二:

    在不创建临时变量的情况下进行交换两个数。既然不能创建临时变量,那么就需要采取异或运算

    对bit进行异或运算。

    1 a^=b 将a和b bit中不一样的点位提取出来存入a

    2 b^=a 将b中和a中不一样的点位取反,也就实现了b=a

    3 a^=b 将a中和b不一样的点位取反,也就实现了a=b

    例如a=3:0011 b=7:0111

    a^=b  a=0100

    b^=a  b=0011=3

    a^=b  a=0111=7

    代码实现

    void swap_without_temp(int *a, int *b)

    {

        (*a) ^= (*b);

        (*b) ^= (*a);

        (*a) ^= (*b);

    }

    三:

    不进行移位操作判断数字的bit有多少个1

    代码如下:

    int count_bit_1(int a)

    {

        int count = 0;

        while (a > 0)

        {

            count++;

            a = a & a - 1;

        }

        return count;

    }

    n-1发生了什么

     

    (1)     二进制数n,n-1后,如果最后一位是0,将向前一位借2,2-1=1。最后一位为1。如果前一位为0,将继续向前一位借2,加上本身少掉的1.则变为1。一直遇到1。减为0.

     

    所以 二进制 xxxx10000-1 = xxxx01111

     

    (2)     n&n-1

     

    按照上述 n=xxxx10000,n-1=xxxx01111

     

    xxxx10000

     

    xxxx01111

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。

    找出那个只出现了一次的元素。 相同的值进行异或等于0,如果其余元素都出现两次,而只有一个元素出现一次,那么把数组中所有的

    元素都进行异或运算

    int findOnce(int arr[], int size)

    {

        int i;

        int result;

        result = 0;

        for (i = 0; i < size; i++)

        {

            result ^= arr[i];

        }

        return result;

    }

    给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。找出只出现一次的那两个元素。

    1 首先将所有元素进行异或运算,得到的结果是仅出现一次的两个元素异或值

    2 采用differ &= -differ 得到只出现在其中一个元素中的1个点位

    3 用该点位去和数组中的元素做与运算。这个点位存在的所有数在一起做异或,这个点位不存在的所有数一起做异或

    这样就可以将区分的做异或运算从而分别得到两个值

    void findOnce_update(int arr[], int size,int *first,int *second)

    {

        int i;

        int differ;

        differ = 0;

        for (i = 0; i < size; i++)

        {

            differ ^= arr[i];

        }

        differ &= -differ;

     

        for (i = 0; i < size; i++)

        {

            if ((differ & arr[i]) == 0)

                 *first ^= arr[i];

            else

                 *second ^= arr[i];

        }

    }

  • 相关阅读:
    python 找到列表中满足条件的元素
    android activity动画anim
    Maven实战(Maven+Nexus建立私服【Linux系统】)
    linux命令
    服务端工程师入门与进阶 Java 版
    jvm字节占用空间分析
    Spark Streaming容错的改进和零数据丢失
    Spark分布式计算和RDD模型研究
    Apache Curator入门实战
    spark简单总结—短小精悍
  • 原文地址:https://www.cnblogs.com/zhanghongfeng/p/11199248.html
Copyright © 2011-2022 走看看