一种复杂度为O(1)获取两个List差集的算法(JAVA)
1.模型图
两个List的差集为A,合集为B
2.算法思路
1,首先两个指针同时指向两个list的初始位置,若如果当两个值相等时,也即图一所示,指针同时加1,变为图形2
2,当两边list的值较大的一方进行指针加1,另一方list保持不变,如图3
3,当相等时继续指针加1,如图4
4,当两边list的值较大的一方进行指针加1,另一方list保持不变,如图5
5,当两个list,其中有一个执行结束时,跳出循环,如图6
6,然后继续处理后续未结束那个list,直到另一list也结束,如图7
图1
图2
图3
图4
图5
图6
图7
3.代码实现
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
*
* @author liujie
*
* 两个排好序的list获取差集,并集和合集
*/
public class SortList {
private static final long N = 5000000;
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<Integer>();
long t1 = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
list1.add(i);
list2.add(i+1000);
}
long t2 = System.currentTimeMillis();
Iterator<Integer> it1 = list1.iterator();
Iterator<Integer> it2 = list2.iterator();
System.out.println("**********list1**************");
// while (it1.hasNext()) {
// System.out.println("it1.next() = " + it1.next());
// }
System.out.println("**********list2**************");
// while (it2.hasNext()) {
// System.out.println("it2.next() = " + it2.next());
// }
List<Integer> list3 = new ArrayList<Integer>();
Collections.sort(list1);
long t3 = System.currentTimeMillis();
Collections.sort(list2);
long t4 = System.currentTimeMillis();
list3 = getASubB(list1, list2);
long t5 = System.currentTimeMillis();
System.out.println("**********list3**************");
Collections.sort(list3);
Iterator<Integer> it3 = list3.iterator();
// while(it3.hasNext())
// {
// System.out.println("it3.next() = " + it3.next());
// }
System.out.println("(t2 - t1) =" + (t2 -t1));
System.out.println("(t3 - t2) =" + (t3 -t2));
System.out.println("(t4 - t3) =" + (t4 -t3));
System.out.println("(t5 - t4) =" + (t5 -t4));
}
/**
* 两个list的差集
*
* @param a
* @param b
* @return
*/
private static List<Integer> getASubB(List<Integer> a, List<Integer> b) {
List<Integer> c = new ArrayList<Integer>();
int i = 0;
int j = 0;
while(true){
if (a.get(i).equals(b.get(j))) {
i++;
j++;
if(j >= b.size())
{
break;
}
if(i >= a.size())
{
break;
}
}
if (a.get(i).compareTo(b.get(j)) > 0) {
c.add(b.get(j));
j++;
if(j >= b.size())
{
break;
}
}
if (a.get(i).compareTo(b.get(j)) < 0) {
c.add(a.get(i));
i++;
if(i >= a.size())
{
break;
}
}
}
System.out.println("i = " + i + ", j = " + j);
// 临界条件处理
while (i < a.size()) {
c.add(a.get(i));
i++;
}
while (j < b.size()) {
c.add(b.get(j));
j++;
}
return c;
}
}
4,执行结果
针对500万数据进行测试所花费的时间为105ms,效果相当的好!