【问题标题】:combining list of strings with a common element将字符串列表与公共元素组合
【发布时间】:2014-03-08 16:15:21
【问题描述】:

假设我有一个字符串哈希集的向量:

Vector<HashSet<String>> strSetVector = new Vector<HashSet<String>>();

我有 4 个包含以下字符串的哈希集:

"A", "B"
"C", "D"
"B", "C"
"E", "F"

我想组合至少有一个共同值的集合,以便我最终得到:

"A", "B","C", "D"
"E", "F"

明显的解决方案是通过向量和每个哈希集迭代多次以找到共同值,但这需要一段时间来处理向量大小为 1000+ 和大小为 100 的哈希集。我也必须去如果我合并一个哈希集以查看现在是否有其他可以合并的哈希集,则再次通过该过程。例如,第一次向量迭代会将 B,C 组合到 A,B 以便我最终得到:

"A", "B", "C"
"C", "D"
"E", "F"

向量/哈希集的下一次迭代:

"A", "B", "C", "D"
"E", "F"

向量/哈希集的下一次迭代将找不到任何公共字符串,因此没有什么要合并的,我就完成了。

对于看似简单的问题,我想要一个更优雅的解决方案。有什么想法吗?

【问题讨论】:

  • 您使用Vector的任何原因?
  • 我只是出于方便而使用向量来保存哈希集列表。不过,我不必使用矢量。
  • 我建议您使用List,分别。 ArrayList 那么,Vector同步的,而List 不是。

标签: java performance


【解决方案1】:

我不确定我是否正确理解了所有内容。而且我认为“最佳”解决方案也可能取决于集合和列表的大小。 (即列表是否包含 10 个集合,每个集合包含 100000 个元素,或者它是否包含 100000 个集合,每个集合包含 10 个元素)。

但是对于到目前为止提到的数字(1000 个集合,100 个元素),我认为可以使用一个相对简单的解决方案:

  • 浏览集合列表
  • 对于每个集合,遍历其元素
  • 对于每个元素,存储从元素到包含它的集合的映射
  • 当遇到已经有关联集合的元素时,将当前集合和这个现有集合合并,并存储从这个合并集合的所有元素到合并集合的映射

这段代码 sn-p 基于给定的示例,并打印一些调试信息,这可能会使过程更清晰。它还存储了一个compactMap,它将(可能合并的)集合的第一个元素映射到集合本身,以表示每个集合只出现一次的集合。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class MergeListsTest
{
    public static void main(String[] args)
    {
        List<Set<String>> sets = new ArrayList<Set<String>>();
        sets.add(new LinkedHashSet<String>(Arrays.asList("A", "B")));
        sets.add(new LinkedHashSet<String>(Arrays.asList("C", "D")));
        sets.add(new LinkedHashSet<String>(Arrays.asList("B", "C")));
        sets.add(new LinkedHashSet<String>(Arrays.asList("E", "F")));
        //sets.add(new LinkedHashSet<String>(Arrays.asList("D")));
        //sets.add(new LinkedHashSet<String>(Arrays.asList("D", "X")));
        //sets.add(new LinkedHashSet<String>());

        Collection<Set<String>> merged = computeMerged(sets);

        System.out.println("Resulting sets:");
        for (Set<String> s : merged)
        {
            System.out.println(s);
        }
    }

    private static <T> Collection<Set<T>> computeMerged(List<Set<T>> sets)
    {
        Map<T, Set<T>> compactMap = new LinkedHashMap<T, Set<T>>();
        Map<T, Set<T>> map = new LinkedHashMap<T, Set<T>>();
        for (Set<T> set : sets)
        {
            System.out.println("Handle set "+set);

            Set<T> combinedSet = new LinkedHashSet<T>(set);
            for (T t : set)
            {
                Set<T> innerSet = map.get(t);
                if (innerSet != null && !innerSet.isEmpty())
                {
                    System.out.println("Element "+t+" was previously mapped to "+innerSet);

                    T first = innerSet.iterator().next();
                    compactMap.remove(first);
                    combinedSet.addAll(innerSet);

                    System.out.println("Combined set is now "+combinedSet);
                }
            }
            if (!combinedSet.isEmpty())
            {
                System.out.println("Store a mapping from each element in "+combinedSet+" to this set");
                T first = combinedSet.iterator().next();
                compactMap.put(first, combinedSet);
                for (T t : combinedSet)
                {
                    map.put(t, combinedSet);
                }
            }
        }
        return compactMap.values();
    }

}

【讨论】:

  • 不错的一个家伙。有帮助:)
【解决方案2】:

也许我最终会得到一个等效的算法,但我会将其视为一个图表,您希望在其中找到 connected components 的集合。

我将构建adjacency matrix,大小为 n x n(总共 n 个不同的元素,在本例中假设为 100),您可以使用它找到具有线性时间复杂度算法的连接元素集,例如在this answer,其中包含 Java 代码。

要构建邻接矩阵,您必须处理每个 HashSet 并将其元素线性连接,这意味着 O(n),并且任意,例如第一个与第二个,第二个与第三个,...(我不知道'认为没有必要将它们完全互连)。

您的元素是字符串而不是字符这一事实可能会使事情变得有些复杂,但您可以事先创建一个 HashMap (String, Integer) 以将每个元素映射到给定的基数,并在时间上线性地进行初始扫描。对该地图的后续查找应该具有 O(1) 的时间复杂度。

【讨论】:

    猜你喜欢
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 2014-01-09
    • 2018-04-29
    • 2019-05-02
    • 2021-05-19
    相关资源
    最近更新 更多