现在存在两个数组,如何高效快速的找出一个数组有另外一个数组不存在的数。
有朋友说他在一次面试中面试官问:现在有两个数组 a,b,如何快速高效的找出数组b中有数组a中不存在的数。
我们来分析一下这个问题
我们最容易想到的就是两个循环,外层循环数组b,里层循环数组a,如果数组b中的数不存在就记录下来。这样确实可以找到想要的数,但是时间复杂度是O(a.length*b.length), 当数组长度比较大时,不仅效率低,还会导致内存不够用或者内存泄露。显然这个不是我们想要的答案。
中国古代就有一种叫 “ 分而治之 ” 的思想,在皇权时代,皇帝将权利下发给一级官员,一级官员将权利下发给二级官员 如此往下,然后做事的时候,上层官员向下逐层发送命令,下层做完后向上层逐层反馈结果。这样的结果就是效率高,准确性高。
分治思想在算法领域应用很多,堆排序,快速排序,跳表等都是常见的案例。
废话不多说,我直接粘代码吧
import java.util.ArrayList;
import java.util.HashMap;
public class quickSearchArray {
public static void main(String[] args) {
int [] a =new int[100000];
int [] b =new int[99999];
int k=0;
for(int i=0;i<100000;i++){//初始化数组,因为数组比较大我就随便给数组赋值了
a[i]=i+1;
if(i+1!=30&&i+1!=56&&i+1!=500){
b[k]=i+1;
k++;
}
}
long l1=System.currentTimeMillis();
//第一种方式直接双重循环
/*for(int i=0;i<a.length;i++){
int result =0;
for(int j=0;j<b.length;j++){
if(a[i]==b[j]){
result=1;
}
}
if(result==0){
System.out.println("不包含的数:"+a[i]) ;
}
}*/
//第二种将数组划分成100个小数组,然后再找出不存在的数
/*int m=1001 ;
int n=100;
ArrayList<ArrayList<Integer>> towArray=new ArrayList<ArrayList<Integer>>();
for(int i=0;i<m;i++){
towArray.add(new ArrayList<Integer>());
}
for(int i=0;i<b.length;i++){
int index =b[i]/m;
towArray.get(index).add(b[i]);
// System.out.println(b[i]+":"+index);
}
for(int i=0;i<a.length;i++){
int index =a[i]/m;
//System.out.println("不包含的数:"+index);
if(!towArray.get(index).contains(a[i])){
System.out.println("不包含的数:"+a[i]);
}
}
*/
//第三种 构建hashMap
int m=10;
HashMap<Integer,ArrayList<Integer>> map=new HashMap<Integer,ArrayList<Integer>>();
for(int i=0;i<b.length;i++){
int index =b[i]/m;
if(!map.containsKey(index)) {
map.put(index, new ArrayList<Integer>());
}
map.get(index).add(b[i]);
}
for(int i=0;i<a.length;i++){
int index =a[i]/m;
//System.out.println("不包含的数:"+index);
if(!map.get(index).contains(a[i])){
System.out.println("不包含的数:"+a[i]);
}
}
System.out.println("time:"+(System.currentTimeMillis()-l1));
}
}
第一种直接二重循环比较,第二种是将数组划分成100个小数组(可以根据实际调)构建二维数组,第三种和第二种类似,用hash代替二维数组。
根据控制台的输出结果可以发现数组越大,第二,三种效率高出了很多倍。
在实际应用中我们可以将第二种的数组维度扩展到 三围 四维,数组划分条件设置成合适的,第三种的hash的key设计成合适的,尽量使每个小块比较均匀。