java - 递归字符串解压

标签 java algorithm recursion nested compression

我正在尝试解压缩如下所示的字符串:

输入:4(ab)

输出:abababab

输入:11ab

输出:aaaaaaaaaaab

输入:2(3b3(ab))

输出:bbbabababbbbababab

上面的例子都使用下面的递归方法正确地出现了,但是当我输入如下内容时出现问题:

输入:4(ab)a

预期输出:ababababa

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

预期输出:bbbabababbbbbbababa

我意识到问题出现在返回语句“重复返回”的地方。在其当前状态下,递归会继续进行,直到它到达输入字符串的末尾,即使在结束括号之后也是如此。基本上我不知道如何让它在到达结束括号时中断,然后如果还有任何剩余则继续。在 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));

}

最佳答案

使用元组作为递归的返回值,除了累加的字符串外,还提供右括号的索引:

index 0 1 2 3 4 5 6 7 8 9 10
str   2 ( 3 b 3 ( a b ) ) a

  f(0)

  => 2 * f(1)[0] add f(f(1)[1] + 1)  // f(1)[1] is the closing index 

    f(1) => 3 * b + 3 * f(5)[0] add f(f(5)[1] + 1)

    => f(5) returns (ab,8)

    f(1) => bbb + ababab add f(9) // str[9] is closing parenthesis

    => f(1) returns (bbbababab,9)

  => 2 * bbbababab add f(10)

  => bbbabababbbbabababa

JavaScript 代码:

var example = '2(3b3(ab)2(cd3(fg)))ab2(gh2(xz))';

console.log(example);
console.log(decompress(example));

function decompress(s){

  // returns tuple [accumulator, index of closing parenthesis]
  function f(i){
  
    var accum = '',
        mult = '',
        curr = '';
      
    // accumulate all parenthetical groups in this level  
    while (i !== s.length){

      // closing parenthesis
      if (s[i] === ')'){
      
        // add the last decompression
        if (curr !== ''){
          accum += customReplicate(curr,mult);
        }
        
        // exit this call
        return [accum,i];
      }
          
      // character is a digit
      if (!isNaN(parseInt(s[i]))){
      
        // add previous decompression
        if (curr !== ''){
          accum += customReplicate(curr,mult);
          
          curr = '';
          mult = s[i];
          
        } else {
          mult += s[i];
        }
        
        i++;
        
      // character is a character
      } else if (s[i] !== '('){
      
        curr += s[i];
        i++;
        
      // parenthetical group 
      } else if (s[i] === '('){
      
        // recursive call
        [tempAccum,index] = f(i + 1);

        accum += customReplicate(tempAccum,mult);
        mult = '';
        i = index + 1;
      }
    }
    
    return accum + customReplicate(curr,mult);
  }
  
  // initialize the recursion
  return f(0);
}

function customReplicate(str,times){
  return new Array(times === '' ? 1 : parseInt(times))
                 .fill(str).join('');
}

关于java - 递归字符串解压,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40951481/

相关文章:

java - 正则表达式从字符串中删除圆括号

Java2d : Set gradient for a lines

python - 为什么这里会发生递归?

recursion - F# 中偏度的递归公式

Java字符串,从右开始每8个字符后插入一个破折号

algorithm - 婚礼策划人

arrays - 找到最长的子数组

algorithm - 求解 T(n) = 4T(n/2)+n²

javascript - 取消或停止递归 promise 链中的 $timeout

java - 想要从列表访问字符串<List<String>>