一種複雜度爲O(1)獲取兩個List差集的算法(JAVA)

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章