代码之家  ›  专栏  ›  技术社区  ›  Ben Lesh

棘手的算法…在嵌套哈希集中找到多个子集组合?

  •  1
  • Ben Lesh  · 技术社区  · 15 年前

    我有一个问题,我必须在嵌套哈希集中找到多个子集的组合。基本上,我有一个“主”嵌套哈希集,并且从一个“可能”嵌套哈希集集合中,我必须以编程方式找到“可能”的“可能”,它们可能是“主”的同时子集。

    假设我有以下几点:

                var master = new HashSet<HashSet<string>>(new HashSet<string>[] {
                            new HashSet<string>( new string[] { "A", "B", "C"}),
                            new HashSet<string>( new string[] { "D", "E"}),
                            new HashSet<string>( new string[] { "F"})
                        }
                    ); 
                var possible1  = new HashSet<HashSet<string>>(new HashSet<string>[] {
                            new HashSet<string>( new string[] { "A", "B", "C"}),
                            new HashSet<string>( new string[] { "F"})
                        }
                     );
                var possible2 = new HashSet<HashSet<string>>(new HashSet<string>[] {
                            new HashSet<string>( new string[] { "D", "E"})
                        }
                     ); 
                var possible3 = new HashSet<HashSet<string>>(new HashSet<string>[] {
                            new HashSet<string>( new string[] { "F"})
                        }
                     ); 
                var possible4 = new HashSet<HashSet<string>>(new HashSet<string>[] {
                            new HashSet<string>( new string[] { "X", "Y", "Z"})
                        }
                    ); 
                var possible5 = new HashSet<HashSet<string>>(new HashSet<string>[] {
                            new HashSet<string>( new string[] { "A", "B" }),
                            new HashSet<string>( new string[] { "D", "E"})
                        }
                    ); 
    

    所有可能的组合子集:

    possible1 and possible2
    possible3 and possible5
    possible2 and possible3
    possible1
    possible2
    possible3
    possible5
    

    我在想最好的办法。当然,还有蛮力的选择,但如果可以的话,我会尽量避免。

    编辑

    为了进一步说明什么是子集,以下是一些示例,给出了主{{“a”、“B”、“C”}、{“C”、“D”、“E”、“F”}、{“X”、“Y”、“Z”}:

    • {{“A”,“B”}{“C”,“D”}将是
    • {{“A”,“B”,“C”},{“X”,“Y”}将是一个子集
    • {{“A”,“B”},{“A”,“B”}不是子集
    • {{“A”,“B”,“C”},{“C”,“D”,“X”}不是子集

    2 回复  |  直到 15 年前
        1
  •  1
  •   Jaroslav Jandek    15 年前

    public static int IsCsInMaster(HashSet<string> childSubset, List<HashSet<string>> master, int startIndex)
    {
        for (int i = startIndex; i < master.Count; i++)
            if (childSubset.IsSubsetOf(master[i])) return i;
    
        return -1;
    }
    
    public static bool IsChildInMaster(List<HashSet<string>> child, List<HashSet<string>> master)
    {
        foreach (var childSubset in child) if (IsCsInMaster(childSubset, master, 0) == -1) return false;
    
        return true;
    }
    
    public static bool IsChildInMasterMulti(List<HashSet<string>> child, List<HashSet<string>> master)
    {
        Dictionary<int, int> subsetChecker = new Dictionary<int, int>();
        List<IEnumerable<int>> multiMatches = new List<IEnumerable<int>>();
        int subsetIndex;
    
        // Check for matching subsets.
        for (int i = 0; i < child.Count; i++)
        {
            subsetIndex = 0;
            List<int> indexes = new List<int>();
    
            while ((subsetIndex = IsCsInMaster(child[i], master, subsetIndex)) != -1)
            {
                indexes.Add(subsetIndex++);
            }
    
            if (indexes.Count == 1)
            {
                subsetIndex = indexes[0];
                if (subsetChecker.ContainsKey(subsetIndex)) return false;
                else subsetChecker[subsetIndex] = subsetIndex;
            }
            else
            {
                multiMatches.Add(indexes);
            }
        }
    
        /*** Check for multi-matching subsets. ***/ //got lazy ;)
        var union = multiMatches.Aggregate((aggr, indexes) => aggr.Union(indexes));
    
        // Filter the union so only unmatched subset indexes remain.
        List<int> filteredUion = new List<int>();
        foreach (int index in union)
        {
            if (!subsetChecker.ContainsKey(index)) filteredUion.Add(index);
        }
    
        return (filteredUion.Count >= multiMatches.Count);
    }
    

    IsChildInMasterMulti(possible2, master)
    

    {{"A","B"},{"A","B"}} 不过,这个案子。这要困难得多(递归地标记master中使用的子集,甚至可能是单个元素)。

    :第三种方法处理 {{“A”,“B”},{“A”,“B”} 案件以及(和更多)。

        2
  •  0
  •   Jay    15 年前

    尽可能使用最简单的解决方案。

    如果你发现它工作后太慢了,那就优化它。