java 字符串递归_java – 递归字符串解压缩

我正在尝试解压缩看起来如下的字符串:

输入:4(ab)

产出:abababab

输入:11ab

输出:aaaaaaaaaaab

输入:2(3b3(ab))

产出:bbbabababbbbababab

以上示例都使用下面的递归方法正确显示,但是当我输入类似的内容时出现问题:

输入:4(ab)a

预期产量:ababababa

输入:2(3b3(ab))a

预期产量:bbbabababbbbabababa

我意识到问题出现在返回语句“返回重复”中.在当前状态下,递归继续,直到它到达输入字符串的末尾,即使在结束括号之后.基本上我不知道如果到达最后的括号如何让它破坏,然后如果还剩下什么就继续.在2(3b3(ab))a中它应该返回2 *(3b3(ab))a,现在它返回2 *(3b3(ab))a.非常感谢任何帮助,因为我无法理解它.

public static String decompress(String compressedText) throws Exception

{

//BASE CASE

if(compressedText.length() == 1)

{

if(compressedText.charAt(0) == ')')

{

System.out.println("1: " + compressedText);

return "";

}

else

{

System.out.println("2: " + compressedText);

return compressedText;

}

}

//END BASECASE

if(compressedText.charAt(0) == '(')

{

System.out.println("3: " + compressedText);

return decompress(compressedText.substring(1));

}

//IF DOUBLE DIGIT

if(Character.isDigit(compressedText.charAt(0)) == true && Character.isDigit(compressedText.charAt(1)) == true)

{

if(compressedText.charAt(3) != '(')

{

System.out.println("4: " + compressedText);

int i = Integer.parseInt(compressedText.substring(0,2));

String repeated = new String(new char[i]).replace("\0", compressedText.substring(2,3));

return repeated + decompress(compressedText.substring(3));

}

else

{

System.out.println("5: " + compressedText);

int i = Integer.parseInt(compressedText.substring(0,2));

String repeated = new String(new char[i]).replace("\0", decompress(compressedText.substring(2)));

return repeated;

}

}

//END DOUBLE DIGIT

//IF SINGLE DIGIT

if (Character.isDigit(compressedText.charAt(0)) == true)

{

if(compressedText.charAt(1) !='(')

{

System.out.println("6: " + compressedText);

int i = Integer.parseInt(compressedText.substring(0,1));

String repeated = new String(new char[i]).replace("\0", compressedText.substring(1,2));

return repeated + decompress(compressedText.substring(2));

}

else

{

System.out.println("7: " + compressedText);

int i = Integer.parseInt(compressedText.substring(0,1));

String repeated = new String(new char[i]).replace("\0", decompress(compressedText.substring(1)));

return repeated;

}

}

//END SINGLE DIGIT

//IF RIGHT PARENTHESIS

if (compressedText.charAt(0) == ')')

{

if (compressedText.charAt(1) != ')')

{

System.out.println("8: " + compressedText);

return "";

}

else

{

System.out.println("9: " + compressedText);

return decompress(compressedText.substring(1));

}

}

//END

System.out.println("10: " + compressedText);

return compressedText.charAt(0)+decompress(compressedText.substring(1));

}

最佳答案 我注意到的一件事是,当你输出“8:”后返回“”时,你“失去”了最后一个“a”.在那个位置上也应该处理尾随的字符,但是你不能简单地将它们归还 – 无论是直接还是通过解压缩它们 – 因为这会导致bbbabaabaababbbabaabaaba.

遗憾的是,我找不到基于你的代码的解决方案,它返回正确的值(我猜你将部分处理的文本放入递归中有一些奇怪的行为,但我不确定……).

但是,我想到了如何解决这个压缩问题,并想出了两个非递归解决方案.也许他们会帮助您改进解决方案.旁注:我的解决方案假设字符串格式正确,即它没有任何不匹配的括号等.

(我在答案结束时使用了重复功能.)

第一种解决方案使用正则表达式,该表达式搜索数字和后续部分(一个char或括号括起的部分,其中不包含括号本身).这样,括号和单焦点减压从内到外处理.

public static String decompressWithRegex(String s) {

if ((s == null) || (s.length() == 0)) {

return s;

}

// pattern for finding number with either bracket-enclosed, char-only part or single char

Pattern p = Pattern.compile("(\\d+)((?:[^\\d\\(\\)]{1})|(?:\\([^\\d\\(\\)]+\\)))");

String tmp = s;

Matcher m = p.matcher(tmp);

// start searching

while (m.find(0)) {

// first capture group returns count

int count = Integer.parseInt(m.group(1));

// second group is string to repeat (if it's bracket-enclosed, then remove brackets)

String what = m.group(2).replace("(", "").replace(")", "");

// build replacement part

String replacePart = repeat(what, count);

// replace it

tmp = m.replaceFirst(replacePart);

// reset matcher (source of matcher is now the new string)

m.reset(tmp);

}

return tmp;

}

第二种解决方案不使用正则表达式.相反,它对如何处理解压缩做出了一些假设:

>任何未附有支架封闭部件的数字都可以直接使用

就地解压缩,这是先完成的

>通过找到第一个封闭支架来处理支架封闭部件

>然后从那里回来开始搜索开口括号

>这会让你重复一遍

>左边的开括号应该有一个数字然后被搜索和解析

>现在我们掌握了所有信息,更换部件已经建成并放置在正确的位置

>然后搜索下一个结束括号,如果有,则按上述方法处理

>如果没有右括号,则解压缩该字符串

码:

public static String decompressWithSearching(String s) {

if ((s == null) || (s.length() == 0)) {

return s;

}

// replace non-groups first

for (int i = s.length() - 1; i >= 0; i--) {

// find digit that is not followed by bracket

if (Character.isDigit(s.charAt(i)) && s.charAt(i + 1) != '(') {

// string to repeat is right behind the digit

String part = s.substring(i + 1, i + 2);

// find complete digit

String countStr = "";

int j = i;

for ( ; j >= 0 && Character.isDigit(s.charAt(j)); j--) {

countStr = s.charAt(j) + countStr;

}

int count = Integer.parseInt(countStr);

// build replacement part

String replacePart = repeat(part, count);

// replace part

s = s.substring(0, j + 1) + replacePart + s.substring(i + 2);

}

}

// replace nested parts

int closing;

while ((closing = s.indexOf(')')) > -1) {

// find matching opening bracket

int opening = s.lastIndexOf('(', closing);

// text between is to be repeated

String what = s.substring(opening + 1,closing);

// find complete digit

String countStr = "";

int numPartIndex = opening - 1;

while (numPartIndex >= 0 && Character.isDigit(s.charAt(numPartIndex))) {

countStr = s.charAt(numPartIndex) + countStr;

numPartIndex--;

}

int count = Integer.parseInt(countStr);

// build replacement part

String replacePart = repeat(what, count);

// replace part

s = s.substring(0, numPartIndex + 1) + replacePart + s.substring(closing + 1);

}

return s;

}

重复字符串的实用方法:

public static String repeat(String what, int times) {

if ((times <= 0) || (what == null) || (what.length() == 0)) {

return "";

}

StringBuilder buffer = new StringBuilder(times * what.length());

for (int i = 0; i < times; i++) {

buffer.append(what);

}

return buffer.toString();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值