查找数组集中常见的元素集

时间:2014-07-09 07:05:03

标签: arrays algorithm

假设有几个数组:

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)

我是否可以尝试其他方法来改善时间和内存复杂性 - 考虑到每个包含数百个元素的千位输入文件?

3 个答案:

答案 0 :(得分:0)

我会使用以下方法。

  1. 扫描整个数据以获取数据中出现的一组元素。
  2. 维护每个元素的计数器;再次扫描数据并增加每个元素的计数器。
  3. 丢弃少于2次的所有元素。
  4. 生成剩余元素的所有可能子集。对于每个子集,如果出现任何元素,则扫描数据并输出每个数组标识符。

答案 1 :(得分:0)

使用哈希图(或地图,如果您需要担心碰撞)。下面的伪代码:

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])结合使用,因此您可以应用相同的哈希映射方法,这次反转键。

答案 2 :(得分:0)

这个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]

虽然它与预期的输出不完全相同,但它确实包含了生成它的所有信息,并且更加紧凑。如果预期会有大量输入行,那么可能值得采用一种方法使存储的信息尽可能紧凑,并且我已尝试遵循此指南。