簡體   English   中英

比較Java中常見元素列表的更快方法?

[英]A faster way to compare lists for a common element in Java?

我有一個用LinkedLists實現的圖形(用Vector實現),我想連接不共享任何公共元素的LinkedLists。 我認為我現在的操作方式需要O(n ^ 3)。 我有一個循環遍歷Vector的for循環,然后是一個嵌套的for循環遍歷Vector的for循環(以便可以將每個List與其他List進行比較),然后在該for循環中我使用遞歸來比較List。

在以這種方式嘗試之前,我嘗試在2nd for循環中使用while循環來遍歷每個列表,並使用二進制搜索來查看2nd列表是否包含每個元素,但是我認為這花費了相同的時間或更長的時間。 這是我的循環:

 public void addEdges(){
  for(int i =0; i < size()-1; i++){
   for(int j = i+1; j < size(); j++){
    if(compatible(get(i),get(j),1,1)){
     get(i).linkTo(get(j));
     get(j).linkTo(get(i));
    }
   }
  }
 }

這是我的遞歸:

 public boolean compatible(Row a, Row b, int indexA, int indexB){
  if(a.get(indexA).getEnd() == b.get(indexB).getEnd()){
   return false;
  }
  else if(a.get(indexA).getEnd() == 0){
   return true;
  }
  else if(a.get(indexA).getEnd() > b.get(indexB).getEnd()){
   return compatible(a,b,indexA+1,indexB);
  }
  else{
   return compatible(b,a,indexB+1,indexA);
  }
 }

假設我正確地閱讀了此內容,則可以用對Collections.disjoint靜態方法的調用來替換compatible方法。

編輯:代碼示例:

public void addEdges(){
  for(int i =0; i < size()-1; i++){
   for(int j = i+1; j < size(); j++){
    if(Collections.disjoint(get(i),get(j))){
     get(i).linkTo(get(j));
     get(j).linkTo(get(i));
    }
   }
  }
 }

我可以嘗試反向索引, element -> [IDs of containing lists] 遍歷索引將告訴您哪些列表共享元素,因此無法連接。

  • 步驟1:建立反向索引
  • 步驟2:創建不兼容索引, list ID -> [IDs of incompatible lists]
  • 步驟3:遍歷不兼容映射以加入兼容列表。

如果存在用於加入兼容列表的特定規則,則步驟3可能會更加復雜,因為兼容性不是暫時的。


一些偽Java:為了我自己,我將假設數據結構看起來像這樣(可能我的Bin是您的Row ,或多或少):

class Bin {
    ID id;
    LinkedList<Element> list;
}

箱的集合allBins的類型為Collection<Bin>

步驟1:反向索引的類型為MultiValueMap<Element, ID> 也就是說,每個元素都映射到一組ID(包含該元素的容器的ID)。

MultiValueMap<Element, ID> reverseIndex;

for (Bin bin : allBins) {
    for (Element e : bin) {
        reverseIndex.put(e, bin.id);
    }
}

步驟2:不兼容索引的類型為MultiValueMap<ID, ID> ,其中每個容器ID都映射到不兼容容器的容器ID集合。

MultiValueMap<ID, ID> incompatibilityIndex;

for (Element e : reverseIndex.keySet()) {
    List<ID> binsWithE = reverseIndex.get(e);
    for (ID id : binsWithE) {
        incompatibilityIndex.putAll(id, binsWithE); // each bin is incompat with itself
    }
}

步驟3:現在,我們可以將彼此不兼容的映射中沒有的任何兩個垃圾箱合並。 由於將兩個垃圾箱合並會改變不兼容性,因此我們必須更加棘手:

Set<Bin> binsRemainingToProcess; // == original allBins
Set<Bin> binsProcessed; // == new allBins

while (binsRemainingToProcess.size() > 0) {
    Bin bin = // grab any bin to work on from binsRemainingToProcess

    // grab any compatible bins
    // could iterate until we find one, but I'm going to compute all compatible
    List<ID> compatibleBinIDs = // all bin IDs in binsRemaining...
    List<ID> incompatibleBinIDs = incompatibilityIndex.get(bin.id);
    compatibleBinIDs.removeAll(incompatibleBinIDs);

    if (compatibleBinIDs.size() > 0) {
        Bin otherBin = // some bin with ID in compatibleBinIDs

        // joining the two bins -- means joining the inner lists,
        // but also joining the incompatibilities
        joinDataStructures(bin, otherBin);
        incompatibilityIndex.putAll(bin.id, incompatibilityIndex.get(otherBinID));

        // we don't need the other bin anymore, but we may be able to join
        // the first bin to others
        binsRemainingToProcess.remove(otherBin);
    } else {
        // couldn't join with anyone; we're done with this bin and can move on
        binsRemainingToProcess.remove(bin);
        binsProcessed.add(bin);
    }
}

好的,最后一個比我計划的要詳細得多。

我意識到您正在尋找一種更快的方法來執行此操作,並且我認為@Michael Brewer-Davis提出了一種更好的方法來執行此操作,但是在創建列表之前是否可以解決該問題? 因此,與其在創建列表時進行比較,不如在創建列表時進行比較,這樣就不必殘酷地遞歸嗎? (我的意思可能是設計變更:僅比較不平等元素一次,以便將不相關的元素自然地組合在一起,並可能避免遞歸)

我實際上想到了一種比較列表的更快方法。 我列出了所有可能的元素,現在代替了元素列表,而是創建了一個long數組,long的每一位代表它們是否包含可能元素列表中的相應元素。 然后,我使用&運算符比較多頭,以了解它們是否具有任何共同的元素。

暫無
暫無

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

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