簡體   English   中英

從數字列表中生成所有唯一對,n選擇2

[英]generating all unique pairs from a list of numbers, n choose 2

我有一個元素列表(比方說整數),我需要進行所有可能的2對比較。 我的方法是O(n ^ 2),我想知道是否有更快的方法。 這是我在Java中的實現。

public class Pair {
 public int x, y;
 public Pair(int x, int y) {
  this.x = x;
  this.y = y;
 }
}

public List<Pair> getAllPairs(List<Integer> numbers) {
 List<Pair> pairs = new ArrayList<Pair>();
 int total = numbers.size();
 for(int i=0; i < total; i++) {
  int num1 = numbers.get(i).intValue();
  for(int j=i+1; j < total; j++) {
   int num2 = numbers.get(j).intValue();
   pairs.add(new Pair(num1,num2));
  }
 }
 return pairs;
}

請注意,我不允許自我配對,因此應該有((n(n + 1))/ 2)-n個可能的配對。 我目前有什么作品,但是隨着n的增加,我花了很長時間忍受不了。 有什么辦法可以將上面的O(n ^ 2)算法變成次二次方程式? 任何幫助表示贊賞。

順便說一句,我也嘗試了下面的算法,但是當我進行基准測試時,它的性能比上面的還要差。 我以為可以避免內部循環,從而可以加快速度。 下面的這種算法不應該更快嗎? 我認為這是O(n)? 如果沒有,請解釋並讓我知道。 謝謝。

public List<Pair> getAllPairs(List<Integer> numbers) {
 int n = list.size();
 int i = 0;
 int j = i + 1;
 while(true) {
  int num1 = list.get(i);
  int num2 = list.get(j);
  pairs.add(new Pair(num1,num2));

  j++;

  if(j >= n) {
   i++;
   j = i + 1;
  }

  if(i >= n - 1) {
   break;
  }
 }
}

好吧,你不能,對吧?

結果是一個包含n*(n-1)/2元素的列表,無論這些元素是什么,僅填充此列表(用零表示)就需要O(n^2)時間,因為n*(n-1)/2 = O(n^2) ...

您不能使其成為次二次方,因為正如您所說-輸出本身就是二次方-並且要創建它,您至少需要#elements_in_output ops。

但是,您可以進行一些“作弊”操作以立即創建列表
您可以創建實現Iterable<Pair> CombinationsGetter類,並實現其Iterator<Pair> 這樣,您將能夠動態訪問元素,而無需先創建列表,這可以減少應用程序的延遲。

注意 :它將仍然是二次方! 即時生成列表的時間只會在更多操作之間分配。


編輯:另一個解決方案,它比幼稚的方法快-是多線程
創建幾個線程,每個線程都將得到他的數據“切片”,並生成相關對,並創建自己的部分列表。
以后-您可以使用ArrayList.addAll()將這些不同的列表轉換為一個。
注意:盡管復雜度為O(n^2) ,但它可能會更快-因為成對創建是並行完成的,而ArrayList.addAll()的實現要比瑣碎的一對一插入操作更有效。

EDIT2:即使它是一個“單個循環”,您的第二個代碼仍然是O(n^2) -循環本身將重復O(n^2)次。 看看你的變量i 僅當j==n ,它增加;當這樣做時,它將j減少回i+1 因此,它將導致n + (n-1) + ... + 1次迭代,這是算術級數的總和 ,並使我們回到預期的O(n^2)

我們無法再達到O(n ^ 2),因為我們正在嘗試創建O(n ^ 2)個不同的Pair對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM