两个已排序的List<Integer>求其交集
近日参加的一个游戏公司的笔试,其中的一个题如下:给定两个已排序的整型列表List<Integer> List0与List1,求出其交集,要求速度最快,额外占用空间最少的算法?
当时的想法没怎么完善,想到用Map,或Hashtable,但是实现起来不知道如何做,于是只写了双重for循环来实现,最后面试官好像不太满意,提醒我说“已排序”。仔细想过之后,用Set实现会比较好。具体实现如下。这样应该达到要求了吧。发现游戏公司的要求挺高,不过很向往的。加油!
package day01;
import java.util.*;
public class ListCross {
/**
* @author zhaohuafei
* @param args
*/
public static void main(String[] args) {
ListCross ls = new ListCross();
List<Integer> list0 = new ArrayList<Integer>();
list0.add(1);
list0.add(2);
list0.add(3);
list0.add(4);
list0.add(5);
list0.add(6);
List<Integer> list1 = new ArrayList<Integer>();
list1.add(3);
list1.add(4);
list1.add(5);
list1.add(6);
List<Integer> list = ls.getListCross(list0 , list1);
System.out.println(list);//[3, 4, 5, 6]
}
public List<Integer> getListCross(List<Integer> list0, List<Integer> list1) {
/**
* 先遍历size小的list每个元素(这个list设为la,另一个为lb),
* 遍历时与另个list中元素比较,
* 找到相同的元素,因为是排序的,假设为升序。
* la中每下一个元素都不必与lb的第一个开始比较,
* 而是接着上个元素比较完之后的剩余元素直至相同
*/
List<Integer> la = list0;
List<Integer> lb = list1;
List<Integer> lc = new ArrayList<Integer>();
int a = list0.size();
int b = list1.size();
int bs = b;// size of the longer list
if (a > b) {
la = list1;
lb = list0;
bs = a;
}
int c = 0;// 与lb中哪个元素开始比较
for (Integer i : la) {
for (int k = c; k < bs; k++) {
if (lb.get(k) > i)
break;// lb.get(k)大于i 则lb的下一个元素也只会比i大所以
// 就不用再执行了
if (lb.get(k) == i)// cross
{
c = k + 1; // 这个地方比较重要,lb中下次就c以前的就不用比较 了
lc.add(i);
break;
}// if
}// for
}// for
return lc;
}
}