簡體   English   中英

查找數組集中共有的元素集

[英]Finding set of elements common in set of arrays

假設有幾個數組:

A. [1,2,3,4,5,6,7,8,9,10]
B. [2,4,6,8,10]
C. [1,4,7,10]
D. [1,3,5,7,9]
.
.

我需要找出所有可能的元素集(1,2,3,4,5 ...),每個元素在至少2個數組(A,B,C ....)中是常見的,並在其中顯示如下方式:

(2,4,6,8,10) -> (A,B)
(1,4,7,10) -> (A,C)
(1,3,5,7,9) -> (A,D)
(4,10) -> (A,B,C)
(1,7) -> (A,C,D)

實際輸入是包含字符串的文件。 可能有成千上萬個文件,每個文件可能包含一百多個密鑰字符串。

我嘗試了以下方法:首先,我通過比較所有可能的數組對來生成元素集。 然后,我嘗試使用邏輯生成其他集合-元素集的相交在數組集的並集中很常見。 像這樣:

(2,4,6,8,10) -> (A,B)
(1,4,7,10) -> (A,C)

從上面我們可以得到:

    intersect((2,4,6,8,10),(1,4,7,10)) -> union((A,B),(A,C))
or, (4,10) -> (A,B,C)

還有什么我可以嘗試改善時間和內存復雜性的方法-考慮千個輸入文件,每個文件包含數百個元素?

我將使用以下方法。

  1. 掃描整個數據以獲得在數據中出現的一組元素。
  2. 為每個要素維護一個計數器; 再次掃描數據,並增加每個元素的計數器(如果出現)。
  3. 丟棄所有發生少於2次的元素。
  4. 生成其余元素的所有可能子集。 對於每個子集,如果發生集合中的任何元素,則掃描數據並輸出每個數組標識符。

使用哈希圖(或地圖,如果您需要擔心碰撞)。 偽代碼如下:

for file in file_list:
   for word in file:
      hash_map[word].append(file)

for wordkey in hash_map:
   print pick_uniques(hash_map[wordkey])

這種方法具有復雜度O(單詞總數),而忽略了每個單詞的長度。

編輯:由於您還希望將wordkey與相同的pick_uniques(hash_map[wordkey])組合在一起,因此您可以應用相同的hash-map方法,這一次是將鍵反轉。

這個Java類:

public class Store {
Map<Integer,Set<String>> int2keyset = new HashMap<>();
Set<Set<String>> setOfKeyset = new HashSet<>();

public void enter( String key, Integer[] integers ){
    for( Integer val: integers ){
        Set<String> keySet = int2keyset.get( val );
        Set<String> newKeySet = null;
        if( keySet == null ){
            newKeySet = new HashSet<String>();
            newKeySet.add( key );       
        } else {
            newKeySet = new HashSet<>( keySet );
            newKeySet.add( key );
        }
        setOfKeyset.remove( newKeySet );
        setOfKeyset.add( newKeySet );
        int2keyset.put( val, newKeySet );
    }
}

public void dump(){
    Map<Set<String>,Set<Integer>> keySet2intSet = new HashMap<>();
    for( Map.Entry<Integer,Set<String>> entry: int2keyset.entrySet() ){
        Integer intval = entry.getKey();
        Set<String> keySet = entry.getValue();
        Set<Integer> intSet = keySet2intSet.get( keySet );
        if( intSet == null ){
            intSet = new HashSet<Integer>();
        }
        intSet.add( intval );
        keySet2intSet.put( keySet,intSet );
    }
    for( Map.Entry<Set<String>,Set<Integer>> entry: keySet2intSet.entrySet() ){
         System.out.println( entry.getValue() + " => " + entry.getKey() );
}
}
}

當喂入問題中給出的行時,將產生:

[2, 6, 8] => [A, B]
[3, 5, 9] => [A, D]
[4, 10] => [A, B, C]
[1, 7] => [A, C, D]

盡管它與預期輸出不完全相同,但它確實包含產生該結果的所有信息,並且更加緊湊。 如果預期會有大量的輸入行,那么可能值得追求一種使存儲的信息盡可能緊湊的方法,我已經嘗試遵循該指南。

暫無
暫無

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

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