JAVA位运算题有1千万个随机数,随机数的范围在1到1亿之间。现在要求写出一种算法,将1到1亿之间没有在随机数中的数求出来?

1. 这个题目源自于位运算时候看到的问题,题目可以做个简化如: 有5个随机数,范围在0-9之间,写算法将不在随机数中的数进行求出来。

有随机数[4, 8, 7, 5, 7],则不在其中的随机数为0 1 2 3 6 9

2. 思路

  1. 常规思路就是开辟一个长度为10的数组,将随机数遍历并放入数组指定的索引位置,并改变对应索引的值为1,则值为0索引为目标不存在的数。 假设我们开辟的是int型数组,每个int占32位,一共需要的是32 * 10 = 320bit = 40byte

  2. 另外一种做法则是借助bitmap进行位运算,其思想就是0表示该位置对应的数没有,1表示存在,如4,我们用比特表示则位10000,第四位为1,说明存在4。(具体位运算的基础知识,参考位运算)对于10个数,我们只需要 10个bit位即可进行表示,非常之节省空间。

3. 借助BitSet进行运算

T

public class Test {
    public static void main(String[] args) {
        Random random = new Random();
        List<Integer> list = new ArrayList<>();
        // 创建5个随机数,每个数字再0-10范围内(左闭右开)
        for (int i = 0; i < 5; i++) {
            list.add(random.nextInt(10));
        }
        System.out.println("产生的随机数为:" + list);
        // 使用bitset,无参默认是64bit,参数表示你想放置的数字范围
        BitSet bitSet = new BitSet(10);
        for (int i = 0; i < list.size(); i++) {
        	// 使用set方法,向开辟的10个bit位放元素,如将4放入,则在位图中存放形式为:
        	// 0000010000
            bitSet.set(list.get(i));
        }
        // 遍历10位bit,对bit位为0的进行输出(0表示无元素,1表示有元素)
        for (int i = 0; i < 10; i++) {
        	// 用get函数,boolean get(int index),false表示为0
            if (!bitSet.get(i)) {
                System.out.println(i);
            }
        }
    }
}

4. 即然了解了位图是干什么的,那么再来举个例子,巩固一下

问题:如何在1到n的连续整数缺失两个数,如何找到缺失的两个数字?
在这里插入图片描述
方法1:假如我们有数组[1,2,3,4,5],其中1,5 缺失,我们可以利用x+y和x*y求出缺失。假设缺失设为x和y,则有

x + y + 2 + 3 + 4 = (1+5)*5 / 2;
x * y * 2 * 3 * 4 = 1 * 2 * 3 * 4 * 5;
相信看到这,你已经觉得开销很大了,那么请看方法2

方法2:同样利用位图,那么只占用很少的内存即可找出缺失

public class Test {
    public static void main(String[] args) {
    	// 当然对缺失任意位数的都可以找到
    	// 假设缺失两个数字5, 9
        printMissingNumber(new int[]{1, 2, 3, 4, 6, 7, 8, 10}, 10);
    }
    private static void printMissingNumber(int[] numbers, int count) {
        int missingCount = count - numbers.length;
        BitSet bitSet = new BitSet(count);

        for (int number : numbers) {
            bitSet.set(number - 1);
        }

        System.out.printf("Missing numbers in integer array %s, with total number %d is %n",
                Arrays.toString(numbers), count);
        int lastMissingIndex = 0;

        for (int i = 0; i < missingCount; i++) {
            lastMissingIndex = bitSet.nextClearBit(lastMissingIndex);
            System.out.println(++lastMissingIndex);
        }
    }
}

参考代码

5. 思考

上述的题解只是做个例子,位图一般适用于大数据中的找出,查重等工作。如在1亿数据中查询某些不存在的数就可以使用该方法。数组的形式占用空间是位图占用空间的32倍(int型举例)。
第一次研究位运算,若有问题,恳请指出。

发布了103 篇原创文章 · 获赞 55 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/l8947943/article/details/105064982