java 使用递归打印列表的每个可能的子列表

o2g1uqev  于 2023-03-06  发布在  Java
关注(0)|答案(3)|浏览(130)

我在解决这个递归问题时遇到了麻烦。递归是很难理解的,而且对我来说也很难编码。问题是要写一个递归方法来找到给定列表的每个可能的子列表。你的方法应该接受一个字符串列表作为参数,并打印出每个可以从该列表的元素创建的子列表。每行一个。2假设没有重复项并且列表不为空。3不要使用任何循环。
我能想到的唯一可能的方法是使用for循环或使用更多的参数,但我不能按指令。这是我目前所拥有的。我检查了列表API,它说有一个子列表方法可以使用。我能够打印前5个可能的子列表,只需从每次递归的列表大小中减去-1,然后我得到一个索引错误。这是非常令人沮丧的,所以如果任何人有任何提示或指针,将非常感谢。
如果你能用循环来解它,我很想看看你是怎么解的。

public static void main(String[]args){
        ArrayList<String> list = new ArrayList<>(List.of("Janet", "Robert", "Morgan", "Char"));
        subsets(list);
        
    }

public static void subsets(List<String> list) {
        int n = list.size();
        if(list.isEmpty()){
            System.out.println(list);

        }
        if(n > 0){
            System.out.println(list.subList(0 , n));
        }
        subsets(list.subList(0,n -1));
    }

Results of my code

j1dl9f46

j1dl9f461#

我想到的最好的解决方案是基于随机性的,我将发表,即使这不是Java编程教科书所期望的。
您可以计算在N个元素的列表中存在K个元素的不同k组合的数量。例如:

  • 4个元素的组合存在于4个元素的列表中
  • 在4个元素的列表中存在3个元素的4个组合。

这个想法是作为递归方法的参数:

  • 要提取子列表的初始列表
  • 已打印的每个子列表的列表
  • 所需子列表大小的元素数K

然后,您应该具有以下方法签名:

public static void subsets(List<String> list, ArrayList<List<String>> alreadyPrinted, int nbOfElementsInTheSubList);

main方法中的调用将是

subsets(list, new ArrayList<>(), list.size());

现在,在递归方法的主体中,处理如下(伪代码)

  • 从不在alreadyPrinted中的列表中选取 nbOfElementsInTheSubList 个随机元素的子列表,打印它,并将它添加到alreadyPrinted
  • 计算组合数量= * 列表大小()选择子列表中的元素数量 *(即:列表中nbOfElementsInTheSubList-组合的数量)
  • 将其与 alreadyThere 比较,alreadyPrinted 中存在的 nbOfElementsInTheSubList 元素的组合数
  • 如果已经存在=组合编号:列表中有所有可用的nbOfElementsInTheSubList-Combination,可以使用(nbOfElementsInTheSubList - 1)作为最后一个参数递归调用方法
  • else:列表中至少缺少一个可用的nbOfElementsInTheSubList-Combination。请使用相同的nbOfElementsInTheSubList但使用更新的alreadyPrinted重新调用子集

我怀疑这是一个最佳的解决方案,所以我书签您的主题,因为我真诚地好奇的预期代码。

oyxsuwqo

oyxsuwqo2#

如果我们想置换列表中的所有值,那么我们可以使用以下代码-〉

public static void main(String[] args) {
        List<String> list = Arrays.asList("Janet", "Robert", "Morgan", "Char");
        recursiveprint(list,  new boolean[list.size()], "");

    }

    private static void recursiveprint(List<String> list,  boolean b[], String s) {

        System.out.println(s);
        for (int j = 0; j < list.size(); j++) {
            if (b[j] == false) {
                b[j] = true;
                recursiveprint(list,  b, s + list.get(j)+"  ");

                b[j] = false;
            }
        }
    }
1l5u6lss

1l5u6lss3#

(我不知道我怎么会在这里,这个标签真的可能已经开放了2年)
如果你能用循环来解它,我很想看看你是怎么解的。
对于循环来说,这是很平常的,你需要一个startend索引的循环对:

const list = ["Janet", "Robert", "Morgan", "Char"];
for (var start = 0; start < list.length; start++)
  for (var end = start + 1; end < list.length + 1; end++) // end is exclusive
    console.log(list.slice(start, end).join()); // so, this is like list.subList(start,end)

然后,可以将其重写为单个循环,并使其成为while,手动管理索引:

const list = ["Janet", "Robert", "Morgan", "Char"];
var start = 0;
var end = 1;
while (start < list.length) {
  console.log(list.slice(start, end).join());
  end++;
  if (end > list.length) {
    start++;
    end = start + 1;
  }
}

那么一个循环很容易写成"递归":

function sublists(list, start, end) {
  console.log(list.slice(start, end).join());
  end++;
  if (end > list.length) {
    start++;
    end = start + 1;
  }
  if (start < list.length)
    sublists(list, start, end);
}

sublists(["Janet", "Robert", "Morgan", "Char"], 0, 1);

所以,从技术上讲,我们现在是递归的,尽管我们并没有从中受益。
然后我们可以开始往回走,把两个循环分开,并把它们组成一个外-内递归对,巧合的是,内循环(这里的'subsublists()')可能与你最初的尝试非常相似(当然没有例外):

function subsublists(list) {
  console.log(list.join());
  if (list.length > 1)
    subsublists(list.slice(0, list.length - 1));
}

function sublists(list) {
  subsublists(list);
  if (list.length > 1)
    sublists(list.slice(1));
}

sublists(["Janet", "Robert", "Morgan", "Char"], 0);

或者,在Java中:

public static void main (String[] args) {
    ArrayList<String> list = new ArrayList<>(List.of("Janet", "Robert", "Morgan", "Char"));
    sublists(list);
}
public static void subsublists(List<String> list) {
    System.out.println(list);
    if(list.size()>1)
        subsublists(list.subList(0,list.size()-1));
}
public static void sublists(List<String> list) {
    subsublists(list);
    if(list.size()>1)
        sublists(list.subList(1,list.size()));
}

实时版本:https://ideone.com/JU44Jj
输出:

[Janet, Robert, Morgan, Char]
[Janet, Robert, Morgan]
[Janet, Robert]
[Janet]
[Robert, Morgan, Char]
[Robert, Morgan]
[Robert]
[Morgan, Char]
[Morgan]
[Char]

相关问题