递归地找到给定的一组不同整数的所有子集

时间:2018-11-12 22:27:38

标签: algorithm recursion

给定一组不同的整数,我想找到所有可能的子集(对于[1,2,3],代码应打印[1], [1,2], [1,3], [1,2,3], [2], [2,3], [3](不一定按此顺序)。

有一些解决方案(like this one),但是我想做的是重新实现具有新递归且没有for循环的波纹管解决方案通过传递索引:(start = 0)

public void forSolution(List<List<Integer>> res, int[] nums, List<Integer> list, int start) {

    for (int i = start; i < nums.length; i++) {
        List<Integer> tmp = new ArrayList<>(list);
        tmp.add(nums[i]);
        res.add(new ArrayList<>(tmp));
        forSolution(res, nums, tmp, i + 1);
    }
}

我以为我需要将两个整数传递给该方法,一个用于保留索引记录,另一个用于保留起始点,但是我在何时需要执行索引递增(相对于起始增量)时遇到问题)。 任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

我认为,如果您不担心索引,该算法将变得更加容易。

基本思想是,对于任何给定的子列表,原始列表的每个元素都包含或不包含。所有可能的子列表的列表就是包含/不包括每个元素的所有可能组合。

对于递归实现,我们可以考虑两种情况:

  1. 输入列表为空。空列表只有一个子列表,它本身就是空列表。
  2. 输入列表由第一个元素x和其余元素rest组成。在这里,我们可以递归调用函数以获得rest的所有子列表的列表。为了实现在结果中包含和不包含x的想法,我们返回一个包含

    的列表
    • sublists(rest)的每个元素,前面加上x,代表我们原始列表中包含x的所有子列表,以及
    • sublists(rest)的每个元素保持不变(没有x),代表我们原始列表中不包含x的所有子列表。

例如,如果列表为[1, 2, 3],则我们有x = 1rest = [2, 3]。递归调用sublists(rest)产生[2, 3], [2], [3], []。对于每个子列表,我们

  • x(即1)前加上[1, 2, 3], [1, 2], [1, 3], [1],然后
  • 不要在x之前加上[2, 3], [2], [3], []

将这些部分串联起来,得出的总结果为[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []

示例实现:

use strict;
use warnings;

sub sublists {
    if (!@_) {
        return [];
    }
    my $x = shift @_;
    my @r = sublists(@_);
    return (map [$x, @$_], @r), @r;
}

for my $sublist (sublists 1, 2, 3) {
    print "[" . join(", ", @$sublist) . "]\n";
}

输出:

[1, 2, 3]
[1, 2]
[1, 3]
[1]
[2, 3]
[2]
[3]
[]