腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中
网友提供思路:位图法
使用位图法判断整形数组是否存在重复
判断集合中存在重复是常见编程任务之一,当集合中数据量比较大时我们通常希望少进行几次扫描,这时双重循环法就不可取了。
位图法比较适合于这种情况,它的做法是按照集合中最大元素max创建一个长度为max+1的新数组,然后再次扫描原数组,遇到几就给新数组的第几位置上1,如遇到5就给新数组的第六个元素置1,这样下次再遇到5想置位时发现新数组的第六个元素已经是1了,这说明这次的数据肯定和以前的数据存在着重复。这种给新数组初始化时置零其后置一的做法类似于位图的处理方法故称位图法。它的运算次数最坏的情况为2N。如果已知数组的最大值即能事先给新数组定长的话效率还能提高一倍。
示例代码如下:
package com.sitinspring;
/** *//**
* 数组重复探测,时间复杂度为O(n)
*/
public class DuplicatedArrayTest {
public static void main(String[] args) {
int[][] arr= {
{1,2,3,5,3,5,56,534,3,32}, {1,2,3,5},{1,2,3,5,3,5},{0,0,1,2,3,5,56,534,78,32}, };
for(int i=0;i<arr.length;i++) {
System.out.print("数组:");
for(int temp:arr[i]) {
System.out.print(temp+",");
}
System.out.print("中");
System.out.print(hasDuplicatedItem(arr[i])?"存在":"不存在");
System.out.print("重复元素.\n");
}
}
/** *//**
* 判断整形数组中是否有重复数据,时间复杂度为O(n)
* @param arr
* @return
*/
public static boolean hasDuplicatedItem(int[] arr) {
// 扫描数组找最大值
int max=arr[0];
for(int i=1;i<arr.length;i++) {
if(arr[i]>max) {
max=arr[i];
}
}
// 按最大值创建一个新数组
int[] bitArray=new int[max+1];
// 按值向新数组中添值,如value为3则bitArray[3]=1
for(int value:arr) {
if(bitArray[value]!=0) {
// 如果value指向的位置已经不是零,说明之前已经给这一块置1了,立即返回true表示数组有重复
return true;
}
else {
// value指向的位置是零,则置为1表示这一位已经有数存在了
bitArray[value]=1;
}
}
return false;
}
}
输出:
数组:1,2,3,5,3,5,56,534,3,32,中存在重复元素.数组:1,2,3,5,中不存在重复元素.
数组:1,2,3,5,3,5,中存在重复元素.
数组:0,0,1,2,3,5,56,534,78,32,中存在重复元素.