【问题标题】:Finding all subsets of a given set of distinct integers recursively递归查找给定一组不同整数的所有子集
【发布时间】:2018-11-13 07:59:52
【问题描述】:

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

有一些解决方案 (like this one),但我想做的是重新实现下面的解决方案,使用新的递归并且没有 for 循环通过传递索引:(开始 = 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);
    }
}

我认为我需要将两个整数传递给该方法,一个用于保存索引记录,另一个用于保存起点,但是我在何时需要进行索引增量时遇到了问题(vs start increment )。 任何帮助将不胜感激。

【问题讨论】:

标签: algorithm recursion


【解决方案1】:

我认为如果您不关心索引,算法会变得更容易。

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

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

  1. 输入列表为空。空列表只有一个子列表,即空列表本身。
  2. 输入列表由第一个元素 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]
[]

【讨论】:

  • 非常有趣的方法!谢谢@melpomene
  • 你只是将循环隐藏在map中。
  • @n.m. sub mymap { my $f = shift; @_ ? ($f-&gt;(shift), mymap($f, @_)) : () }现在我有一个递归地图。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-07
  • 2014-12-07
  • 2015-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多