一種複雜度爲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,效果相當的好!