如何在没有int参数的情况下递归删除连续重复项?

时间:2015-08-31 03:39:13

标签: java debugging recursion duplicate-removal

我需要修复以前的代码。如果输入是" aabbcdefgghijkllaa",则输出需要是" abcdefghijkla"。我目前使用的代码更改了输出" alkjihgfedcba"。 (输入可能不一定按字母顺序排列,输出的顺序应与原始输入的顺序相同。) 我应该创建一个新的方法来反转它还是有办法用我当前的方法修复它?

这是我的代码:

package recursion;

public class recursion {

    static String a = "aabbcdefgghijkllaa";
    static int b=a.length()-1;
    static String result = "";

    public static void main(String[] args){

        System.out.println("Input: " + a);
        System.out.print("Output: ");
        removeDuplicates(a);
    }

    public static String removeDuplicates(String a){

        if (b <= 0){
            System.out.print(a.charAt(0));
            result=result+a.charAt(0);
        }
        else if (a.charAt(b) == a.charAt(b-1)) {
            b--;
            removeDuplicates(a);              
        }
        else {
            System.out.print(a.charAt(b));
            result=result+a.charAt(b);
            b--;
            removeDuplicates(a);
        }
        return a;
    }
}

将b更改为0(和 - 到+)会产生&#34; a&#34;的输出,这也不是我需要的。我该如何解决这个问题?

4 个答案:

答案 0 :(得分:2)

最好将其分解为具体目标:

  • 当字符串为null或为空
  • 时,您要执行的操作
  • 你想用一串大小的字符&lt; 2
  • 您想要使用大小为&gt; = 2
  • 的字符串

......以及每种情况的条件。

请注意,后面的代码大多未经测试;它意味着给你一个粗略的想法,但不是一个完整的解决方案。它适用于您的示例,但它肯定有一些缺点。

让我们想想当我们得到一个示例字符串“aabccdde”时会发生什么。我们想要跟踪该字符串中的第一个字母以及字符串的其余部分。有任何东西可以附加到任何一方都没有坏处。

有了这个,我们为递归方法提出了这个签名:

private static String deleteConsecutiveDuplicates(String string,
                                                  char lastSeenLetter,
                                                  StringBuilder builder)

这不是你向任何人公开的东西,所以你用另一个做出初始化的方法来掩盖它,“你是空的/是吗?”检查。

static String deleteConsecutiveDuplicates(String string) {

    if(null == string || string.length() == 0) {
        return string;
    } else {
        return deleteConsecutiveDuplicates(string.substring(1),
                                           string.charAt(0),
                                           new StringBuilder());
    }
}

现在让我们谈谈当我们看到字符串时我们会做什么。

第1轮:'a' | "abccdde" | ""

我们上次看到的字符与字符串中的第一个字符相同。

  • 将其添加到构建器
  • 前进到索引[2,n)表示的子字符串,并将“最后看到的字母”作为传入字符串的第1位字符。

第2轮:'b' | "ccdde" | "a"

两个角色完全不同。

  • 附加b
  • 前进到索引[1,n)表示的子字符串,并将“上次看到的字母”作为传入字符串的第0位字符。

重复这些步骤,直到留下字符串"abcde"

这里的意识形态是将问题分解为更容易消化和解决的小问题。一般来说,你只能通过最后看到的字母变量一次添加一个字符。

还有其他一些边缘情况,这个简单的方法并不完全考虑(一个字母,多个重复的实例;即“zzzzzzz”将留下一个“z”),但是希望这会给你一个开始的地方。

private static String deleteConsecutiveDuplicates(String string, char lastSeenLetter, StringBuilder builder) {
    if(string.length() == 0) {
        builder.append(lastSeenLetter);
    } else if(string.charAt(0) == lastSeenLetter) {
        builder.append(lastSeenLetter);
        if(string.length() < 2 ) {
            return builder.toString();
        }
        return deleteConsecutiveDuplicates(string.substring(2), string.charAt(1), builder);
    } else {
        if(builder.charAt(builder.length() - 1) != lastSeenLetter) {
            builder.append(lastSeenLetter);
        }
        return deleteConsecutiveDuplicates(string.substring(1), string.charAt(0), builder);
    }
    return builder.toString();
}

答案 1 :(得分:0)

相反怎么样?

return a.replaceAll("(.)(?=\\1)", "");

这也适用于三元组,即abbbc -> abc。如果您只想要双打,即abbbc -> abbc,请将正则表达式更改为:

return a.replaceAll("(.)\\1", "$1");

答案 2 :(得分:0)

如果你想要一个没有任何字符串位置变量的递归解决方案,你可以试试这个(尽管效果很差):

public class recursion {

    static String a = "aabbcdefgghijkllaa";

    public static void main(String[] args){

        System.out.println("Input: " + a);
        System.out.println("Output: " + removeDuplicates(a));
    }

    public static String removeDuplicates(String a){
        if(a.length() < 2)
            return a;
        return a.charAt(0)+removeDuplicates(a.substring(a.charAt(0) == a.charAt(1) ? 2 : 1));
    }
}

这里removeDuplicates方法不会打印任何内容,它只是形成结果字符串,为子字符串调用自身,如果它与第一个字符相同,则跳过第二个字符。

答案 3 :(得分:-1)

你真的想为此使用递归吗?如果你真的想删除重复的字符,可以使用Set。

来完成
Set s = new HashSet();
String a = "aabbcdefgghijkllaa";
for (int i=0 ;i<a.length();i++) {
    s.add(a.charAt(i));
}
System.out.println(s);