给定一组不同的整数,我想找到所有可能的子集(对于[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);
}
}
我以为我需要将两个整数传递给该方法,一个用于保留索引记录,另一个用于保留起始点,但是我在何时需要执行索引递增(相对于起始增量)时遇到问题)。 任何帮助将不胜感激。
答案 0 :(得分:1)
我认为,如果您不担心索引,该算法将变得更加容易。
基本思想是,对于任何给定的子列表,原始列表的每个元素都包含或不包含。所有可能的子列表的列表就是包含/不包括每个元素的所有可能组合。
对于递归实现,我们可以考虑两种情况:
输入列表由第一个元素x
和其余元素rest
组成。在这里,我们可以递归调用函数以获得rest
的所有子列表的列表。为了实现在结果中包含和不包含x
的想法,我们返回一个包含
sublists(rest)
的每个元素,前面加上x
,代表我们原始列表中包含x
的所有子列表,以及sublists(rest)
的每个元素保持不变(没有x
),代表我们原始列表中不包含x
的所有子列表。例如,如果列表为[1, 2, 3]
,则我们有x = 1
和rest = [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]
[]