【问题标题】:How to Compress a String using Recursion? (RLE algorithm)如何使用递归压缩字符串? (RLE 算法)
【发布时间】:2013-11-25 19:12:48
【问题描述】:

我在尝试使用递归压缩字符串时遇到了一点问题。

例如,考虑以下字符串:

qwwwwwwweeeeerrtyyyyyqqqqwEErTTT

应用RLE算法后,这个字符串被转换成:

q9w5e2rt5y4qw2Er3T

在压缩后的字符串中,“9w”表示9个连续的小写“w”字符的序列。 “5e”表示连续5个小写“e”字符等

我已经有一个无需递归即可压缩它的代码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Compress {

    public static String input(String source) {
        StringBuffer coding = new StringBuffer();
        for (int i = 0; i < source.length(); i++) {
            int runLength = 1;
            while (i+1 < source.length() && source.charAt(i) == source.charAt(i+1)) {

                runLength++;   

                i++;

           }
            if (runLength>1){
            coding.append(runLength);
            }
            coding.append(source.charAt(i));
        }
        return coding.toString();
    }

    public static void main(String[] args) {

        IO.outputStringAnswer("Enter a string");
        String str = IO.readString();
        String result = ""; 
        result=input(str); //function(variable)


        IO.outputStringAnswer(result);
    }
}

但我不确定这是否能够变成它的递归版本。

【问题讨论】:

  • 您当然可以制作它的递归版本,但这样做没有明显的好处。
  • 哦,所以我得重写整个代码?我对这一切还很陌生,所以很遗憾,我还不太习惯用递归编写代码。
  • 为什么要使用递归压缩字符串?我很难找到这样做的理由——至少在 Java 中是这样。
  • 哦,这是我需要完成的作业的一部分,但直到现在我才真正在作业中使用过递归。我查看了一些示例,但似乎无法弄清楚如何让递归用于压缩。
  • 作业是否为使用递归提供了任何指导或理由?这似乎是对递归的一种非常糟糕的使用。

标签: java regex algorithm recursion compression


【解决方案1】:

这很可能是您要查找的内容:

public static String compress(String source) {
    if (source.length() <= 1) return source;

    int runLength = 1;
    while (runLength < source.length() && source.charAt(0) == source.charAt(runLength)) {
        runLength++;
    }

    String lengthString = runLength > 1 ? String.valueOf(runLength) : "";
    return lengthString + source.substring(0,1) + compress(source.substring(runLength));
}

我假设您的源字符串不包含任何数字。如您所见,该函数在最后一行使用源字符串的其余部分递归调用自身。

【讨论】:

    【解决方案2】:

    这是一个有趣的问题。一种根本不使用迭代,只使用递归的解决方案是:

    public static String compressRecursion(String str, char curChar, int curCount) {
        // termination case - reached end of the source string
        if(str.length() == 0)
            return "" + (curCount == 1 ? "" : curCount) + curChar;
    
        // branch on change in next character
        String nextStr = str.substring(1,str.length());
        if(str.charAt(0) == curChar)
            return compressRecursion(nextStr,curChar,curCount + 1);
        else
            return "" + (curCount == 1 ? "" : curCount) + curChar
                    + compressRecursion(nextStr,str.charAt(0),1);
    }
    public static String compress(String source) {
        return compressRecursion(source, source.charAt(0), 0);
    }
    

    这在生产代码中可能没有多大用处,因为任何合理长度的输入都会发生“堆栈溢出”异常,这是因为将为每个函数调用创建一个新的堆栈框架,从而在输入。 Java 并不是真正为运行这样的代码而设计的。

    用 scheme 编写的同义压缩函数(没有迭代结构):

    (define (num2str num)
      (if (= 1 num) "" (number->string num)))
    
    (define (first-char str)
      (substring str 0 1))
    
    (define (next-string str)
      (substring str 1 (string-length str)))
    
    (define (compress str char count)
      (cond [(= 0 (string-length str)) (string-append (num2str count) char)]
            [(string=? char (first-char str))
              (compress (next-string str) char (+ count 1))]
            [ else 
              (string-append (num2str count) char
                (compress (next-string str) (first-char str) 1))]))
    
    (define (compressStart str)
      (compress str (first-char str) 0)) 
    

    类似scheme的函数式语言将使用尾递归优化来防止堆栈溢出,并使函数调用比Java等命令式语言更轻量级的操作。

    【讨论】:

      猜你喜欢
      • 2015-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多