递归字符串函数(Java)

时间:2010-05-05 23:27:51

标签: java string recursion

我正在尝试设计一个基本上如下的函数:

String s =“BLAH”;

将以下内容存储到数组中: 胡说 啦 呸 BLH BLA BL BA BH 啊 人

所以基本上我在那里做的就是一次一个地减去每个字母。然后一次减去两个字母的组合,直到剩下2个字符。将这些代中的每一代存储在一个数组中。

希望这是有道理的,

杰克

3 个答案:

答案 0 :(得分:2)

你是怎么得到'al'的?这些混在一起吗?

我会创建一个HashSet来保存所有排列并将其传递给递归方法。

void foo(HastSet<String> set, String string) {
    if (string.length < 2) // base case
        return
    else {
        // add the string to the hashset
        set.add(string);

        // go through each character
        for (int i = 0; i < string.length; i++) {
            String newString = s.substring(0,i)+s.substring(i+1);
            foo(set, newString);
        }
    }
}

如果您关心唯一性,那就是这样。如果没有,您可以使用Vector。无论哪种方式,您都可以使用toArray来恢复阵列。

答案 1 :(得分:1)

这是@ voodoogiant答案的优化。基本上我想推迟单词构建任务,直到递归的基本情况。这样你就可以使用StringBuilder来构建单词。所以递归的作用基本上是打开和关闭一个布尔数组的位,这个位说明是否必须在下一个单词中使用某个字母。

暂时没有编写java代码,如果没有编译的话,请原谅我。

void buildWords(String baseWord, boolean[] usedLetters, HashSet<String> words, int index){
    if (index == baseWord.length()){
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < index; i++){
            if (usedLetters[i])
                builder.append(baseWord.characterAt(i));
        }
        words.add(builder.toString());
    }
    else{
        usedLetters[index] = true;
        buildWords(baseWord, usedLetters, words, index+1);
        usedLetters[index] = false;
        buildWords(baseWord, usedLetters, words, index+1);
    }
}

你需要注意的事情:

  1. 这可以构建空字符串(如果数组的位置为f​​alse)。
  2. 这可以构建重复的单词(如果baseWord有连续的重复字符),我不记得HashSet在添加重复键时是否抛出异常。
  3. 不记得在末尾追加char的StringBuilder方法是否称为“append”,但是你明白了。
  4. 不记得输出构建的字符串的StringBuilder方法是否是“toString”,但你也明白了。

答案 2 :(得分:0)

你真的不需要递归来做这件事。这是一个迭代算法:

    String master = "abcd";
    final int L = master.length();

    List<String> list = new ArrayList<String>();
    list.add(master);
    Set<String> current = new HashSet<String>(list);
    for (int i = L-1; i >= 2; i--) {
        Set<String> next = new HashSet<String>();
        for (String s : current) {
            for (int k = 0; k < s.length(); k++) {
                next.add(s.substring(0, k) + s.substring(k + 1));
            }
        }
        list.addAll(current = next);
    }
    System.out.println(list);
    // prints "[abcd, abc, abd, bcd, acd, ac, ad, ab, bc, bd, cd]"

这基本上是breadth-first search的核心。您从最初包含current的{​​{1}}集开始。然后在String master的每次迭代中,您都会浏览i并生成for (String s : current)集合,您可以通过从next删除所有可能的字符来完成此操作。

有效的Java第2版:第25项:首选列表到数组,但如果您坚持存储在s,则可以在最后执行以下操作。

String[]

另见