使用 Java 8 枚举 K 元素的组合

2024-02-29

给定一个实例List<E>,使用 Java 8 特性,如何构建一个List<List<E>>枚举原始 List 的 k 个元素的所有可能组合?


这是我为解决一些欧拉项目问题而编写的算法:

public static <E> Stream<List<E>> combinations(List<E> l, int size) {
    if (size == 0) {
        return Stream.of(Collections.emptyList()); 
    } else {
        return IntStream.range(0, l.size()).boxed().
            <List<E>> flatMap(i -> combinations(l.subList(i+1, l.size()), size - 1).map(t -> pipe(l.get(i), t)));
    }
}

private static <E> List<E> pipe(E head, List<E> tail) {
    List<E> newList = new ArrayList<>(tail);
    newList.add(0, head);
    return newList;
}

这需要一个List<E>和一个尺寸并返回尺寸列表的所有组合size, as a Stream<List<E>>.

这是一种递归算法:其思想是计算大小的组合size - 1列表中除第一个元素之外的所有元素。当你拥有它们时,你只需在每个组合的开头添加你删除的第一个元素。然后,您继续寻找所有尺寸组合size - 1列表中除第一个和第二个元素之外的所有元素,当您拥有所有元素时,将第二个元素添加回来。这一直持续到您达到size = 0,您只需返回空组合。请注意,此方法确实返回“重复”(如果组合(a, b, c)然后返回(b, c, a)不返回)。

您没有提到是否应包含重复项。修改这个算法以包含重复项并不困难,只是逻辑有点不同。

public static <E> Stream<List<E>> combinationsDupl(List<E> l, int size) {
    if (size == 0) {
        return Stream.of(Collections.emptyList()); 
    } else {
        return l.stream().<List<E>> flatMap(h -> combinationsDupl(subtract(l, h), size - 1).map(t -> pipe(h, t)));
    }
}

private static <E> List<E> pipe(E head, List<E> tail) {
    List<E> newList = new ArrayList<>(tail);
    newList.add(0, head);
    return newList;
}

private static <E> List<E> subtract(List<E> list, E e) {
    List<E> newList = new ArrayList<>(list);
    newList.remove(e);
    return newList;
}

这次,你遍历了输入列表中的所有元素。对于它们中的每一个,您计算删除该元素的列表的组合。然后,当您拥有所有这些组合时,您可以将其再次添加到每个组合中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Java 8 枚举 K 元素的组合 的相关文章

随机推荐