【问题标题】:Find all possible string of length k with recursion使用递归查找所有可能的长度为 k 的字符串
【发布时间】:2021-08-12 13:20:41
【问题描述】:

对于字符串 s = "abcd" ,k=3 那么答案应该是:

abc
abd
acd
bcd

使用递归(k=3)的java代码:

public class SubString {

    static ArrayList<String> al = new ArrayList<>();

    public static void main(String[] args) {
        String s = "abcd";
        findsubsequences(s, ""); // Calling a function
        for (String subString : al) {
            if (subString.length() == 3) {
                System.out.println(subString);
            }
        }
    }

    public static void findsubsequences(String s, String ans) {
        if (s.length() == 0) {
            al.add(ans);
            return;
        }
        findsubsequences(s.substring(1), ans + s.charAt(0));
        findsubsequences(s.substring(1), ans);
    }
}

我想以最快的方式通过递归找到所有可能的长度为 k 的子字符串,并且在 arraylist 中不使用 foreach

【问题讨论】:

  • 问题/问题是什么?代码不起作用吗?不够快/不够高效?
  • 我不想在 main 方法中使用 foreach,我需要像 findsubsequences(String s, int k) 这样的方法来查找所有可能的长度为 k 的子字符串
  • 那么你应该检查findsubsequencesans的长度,当ans足够长时停止深入。
  • 能不能具体帮我写一下,如果我的英文不好见谅

标签: java string algorithm recursion substring


【解决方案1】:

使用回溯逻辑的解决方案(可以泛化以解决任何排列/子集/组合问题)-

public static void main(String[] args) {
    ans = new ArrayList<>();
    String s = "abcd";
    int k = 3;
    generatePermutation(new StringBuilder(""), 0, s.toCharArray(), k);
    System.out.println(ans);
}

private static List<String> ans;

private static void generatePermutation(StringBuilder temp, int st, char[] str, int k){
    if(temp.length() == k){
        // base result
        String br = temp.toString();
        ans.add(br);
        return;
    }
    
    for(int i = st; i < str.length; i++){
        temp.append(str[i]);
        generatePermutation(temp, i + 1, str, k);
        temp.setLength(temp.length() - 1);
    }
}

输出

[abc, abd, acd, bcd]

【讨论】:

  • 而不是temp.setLength(temp.length()-1) 使用temp.deleteChartAt(temp.length()-1) 更明显。
【解决方案2】:

更快/更清洁的解决方案是在达到最大长度时停止迭代。如果长度正确,您应该只添加元素:

public static void findsubsequences(String s, String ans, int maxLength) {
    if (s.length() == 0) {
        return;
    }
    if (ans.length() == maxLength) {
        al.add(ans);
        return;
    }
    findsubsequences(s.substring(1), ans + s.charAt(0), maxLength);
    findsubsequences(s.substring(1), ans, maxLength);
}

此外,您还可以删除 static 结果列表并改为返回结果:

public static void main(String[] args) {
    String s = "abcdefgh";
    List<String> results = findSubsequences(s, "", 3);
    for (String subString : results) {
        System.out.println(subString);
    }
}

public static List<String> findSubsequences(String s, String ans, int maxLength) {
    if (s.length() == 0) {
        return new ArrayList<>();
    }
    if (ans.length() == maxLength) {
        return Collections.singletonList(ans);
    }

    List<String> list = new ArrayList<>(findSubsequences(s.substring(1), ans + s.charAt(0), maxLength));
    list.addAll(findSubsequences(s.substring(1), ans, maxLength));
    return list;
}

【讨论】:

  • 如果您将数组列表作为参数传递并对其进行变异,效果会更好。它可以大大减少分配
  • @JakubDóka 是的,但如果你想走这条优化路线,那么我建议不要递归地这样做。
  • 代码看起来会干净很多,我可以进行编辑吗?
  • findsubsequences("abcd", "", 3); 仅在列表"abc" 中存储al
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-06
  • 2019-07-24
  • 2022-06-23
  • 1970-01-01
  • 2018-10-14
相关资源
最近更新 更多