所以我对Java有点新意,目前正在大学学习CS入门课程。我有一个小问题,一直困扰着我。我有一个写一个递归方法,"解压缩"输入文本使用a"游程编码(RLE)"算法。简而言之,如果输入是" qwwwwwwwwweeeeerrtyyyyyqqqqwEErTTT"输出必须是" q9w5e2rt5y4qw2Er3T"。目前,我的方法将输入分解为只有一个字母而没有数字(qwertyqwErT)。
我的问题是如何实际计算递归的字母数?我不允许在方法之外声明任何变量并且这是我的主要问题,因为我在Stackoverflow上搜索的所有问题大多使用"全局变量"。但是,我可以根据需要声明尽可能多的局部变量。
教授还给了我们一个提示":
提示#1:记住字符用数字代码表示。您可以按如下方式递减字符变量:
char c =' 7&#39 ;; C - ; // c现在将保留角色' 6'
我试着通过在输入的末尾添加一个带编号的字符来解决这个问题,我每次都会使用并递增一个重复的字符然后将其替换为前面的#&# 39;一个新角色,但那也没有。
感谢您的帮助!
编辑:
我应该包括这样一个事实:我不允许使用任何类型的循环,并且我可以假设角色不会重复超过(9)次
答案 0 :(得分:1)
假设您正在使用递归函数调用的返回值来返回压缩字符串,您可以创建另一个参数来跟踪函数被调用的次数。通过使用引用变量,它可以充当一种全局变量"对于该方法调用。
public String compress(..., Integer callCount)
{
callCount++;
...
}
然后从您的调用函数
执行类似的操作Integer callCount;
compress(..., callCount);
System.out.println("Compressed in " + callCount + " iterations");
当然,由于你需要函数本身的值来添加一个字符重复的次数,所以没有什么能阻止你在函数中使用callCount
。
另一种选择是使用静态变量,这类似于使用全局的方法。
答案 1 :(得分:0)
全局变量确实是要避免的事情。幸运的是,你完全不需要它们来实现一个RLE压缩的纯函数。
提示允许您直接使用数字(字符)作为计数器。考虑一下这个片段:
char c = getNextChar();
if (Character.isDigit(c)) {
counter = c;
char_to_decompress = getNextChar();
while (c > '0') {
result.add(char_to_decompress);
c--; // the 'trick'
}
}
当然,这只有在没有超过9个字符的运行时才有效。
WRT递归,除了更换外环之外,我没有看到使用它的好方法。 (任何可以用递归表达的东西都可以用循环表示,反之亦然。)
String decompress(String input) {
if (input == '') return ''; // this stops recursion
int position = 0; // where have we advanced
String result = '';
if (Character.isDigit(input.charAt(position))) {
position += 1;
// ... decompress input.charAt(position) into result
}
else {
result = input.charAt(position); // not compressed
}
// here come recursion
return result + decompress(input.substring(position + 1));
}
当然,这不是经验丰富的Java开发人员所做的,因为剪切和添加字符串非常慢,您必须使用StringBuffer
来收集结果并使用CharSequence
作为输入允许廉价的字符串切片。
但总体思路仍然存在。在字符串为列表的语言中,该算法看起来更好,并且剪切列表的头部是自然操作,递归是表达循环的基本方式。当你知道像Lisp或Haskell或Erlang这样的语言时,你会更清楚地看到这一点。