Arrays 查找数组集合中的公共元素集合

Arrays 查找数组集合中的公共元素集合,arrays,algorithm,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. [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)

考虑到每一个包含数百个元素的数千个输入文件,是否还有其他方法可以尝试提高时间和内存复杂性?

我将使用以下方法

  • 扫描整个数据以获得数据中出现的一组元素
  • 为每个元素维护一个计数器;再次扫描数据,如果出现,增加每个元素的计数器
  • 丢弃出现少于2次的所有元素
  • 生成剩余元素的所有可能子集。对于每个子集,扫描数据并在出现集合中的任何元素时输出每个数组标识符
  • 使用散列映射(或者映射,如果您需要担心冲突)。伪代码如下:

    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
    s与相同的
    pick\u uniques(hash\u 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]