递归生成两个列表之间的每个可能映射的集合(Java)

时间:2017-05-03 01:27:53

标签: java algorithm dictionary recursion

问题

我正在尝试编写一个方法,以递归方式生成并返回一组给定列表中的元素之间的所有可能映射到另一个列表。

例如,假设我输入了一个整数的arraylist和一个字符串的arraylist。

List<Integer> integers = new ArrayList<>();
integers.add(1); integers.add(2);

List<String> strings = new ArrayList<>();
strings.add("a"); strings.add("b"); strings.add("c");

combinations(integers, strings);

这应该返回包含从整数到字符串的所有以下映射的集合。

{
 (1 -> "a", 2 -> "b"), 
 (1 -> "a", 2 -> "c"),
 (1 -> "b", 2 -> "a"),
 (1 -> "b", 2 -> "c"),
 (1 -> "c", 2 -> "a"),
 (1 -> "c", 2 -> "b")
}

这里,每个字符串(值)只能映射到一个整数(键)。换句话说,没有两个整数可以映射到同一个字符串。

免责声明和规格

完全自由裁量权:这是家庭作业分配方法之一的简化​​版本 - 因此方法签名应如下所示

Set<Map<Integer, String>> combinations(List<Integer> integers, List<String> strings);

并且必须使用递归编写。这里假设integers的大小小于或等于strings的大小。我将分享我到目前为止的内容,并解释为什么它不起作用,我需要帮助。

我的尝试(到目前为止!)

public static Set<Map<Integer, String>> combinations(
        List<Integer> integers, List<String> strings) {

    // Return set: The set of all possible mappings from integers -> strings
    Set<Map<Integer, String>> result = new HashSet<>();

    /* Base case: integers is empty => return the empty map.
       NOTE: It is assumed that there are fewer integers than strings. */
    if (integers.isEmpty()) {
        result.add(new HashMap<>());
        return result;
    }

    /* Recursive case: integers is non-empty =>
    *  get the first integer (call it "first") in integers and map it to any
    *  string (call it string) in strings.
    *  Recursively calculate all the mappings from the "rest of integers"
    *  (integers without "first") to the "rest of strings" (strings without
    *  "string").*/
    Integer first = integers.get(0);
    for (String string: strings) {
        Map<Integer, String> thisMap = new HashMap<>();
        thisMap.put(first, string);

        integers.remove(first);
        strings.remove(string);

        result = combinations(integers, strings);
        result.add(thisMap);
    }
    return result;

}

这里输出只是

{
 (),
 (1 -> "a", 2 -> "b")
}

这只是一个包含空地图和第一个可能地图的集合。

如果有人能指出我正确的方向,我们将不胜感激!

1 个答案:

答案 0 :(得分:1)

不是仅提供代码,而是让我给出伪代码,让您了解如何执行此操作。如果您有任何问题,我建议您再试一次,然后再回来:

combinations(keys, values):
    create result set
    for each key in keys
        for each value in values
            combos = combinations(keys without key, values without value)
            for each combo
                add map from key -> value to combo
                add combo to result set
    return result set

更新

现在OP已经接受了这个答案,这是用于演示算法的工作代码:

Set<Map<Integer, String>> combinations(List<Integer> keys, List<String> values) {
    if (keys.isEmpty())
        return Collections.singleton(new HashMap<>());
    else
        return keys.stream().flatMap(k -> 
            values.stream().flatMap(v -> 
                combinations(listWithout(keys, k), listWithout(values, v)).stream()
                    .peek(c -> c.put(k, v)))).collect(toSet());
}

private <T> List<T> listWithout (List<T> input, T value) {
    return input.stream().filter(v -> !v.equals(value)).collect(toList());
}