Java 根据括号中的数字*内容展开给定字符串

Java 根据括号中的数字*内容展开给定字符串,java,string,algorithm,stringbuilder,expansion,Java,String,Algorithm,Stringbuilder,Expansion,我试着取一个给定的字符串,当括号前有一个数字时,括号内的内容就会重复这个次数。我考虑过使用StringBuilder并构建这个函数,但我不确定如何重复括号内的内容。 示例-3(ab)-结果将是ababab,示例-3(b(2(c))结果将是bcc 在我在这里构建的函数中,它重复括号,而不是括号的内容 public static String solve(String s){ StringBuilder sb = new StringBuilder(); int repeat =

我试着取一个给定的字符串,当括号前有一个数字时,括号内的内容就会重复这个次数。我考虑过使用StringBuilder并构建这个函数,但我不确定如何重复括号内的内容。 示例-3(ab)-结果将是ababab,示例-3(b(2(c))结果将是bcc 在我在这里构建的函数中,它重复括号,而不是括号的内容

  public static String solve(String s){
    StringBuilder sb = new StringBuilder();
    int repeat = 0;
    for (char c : s.toCharArray()) {
        if (Character.isDigit(c)) {
            repeat = repeat * 10 + Character.getNumericValue(c);
        } else {
            while (repeat > 0) {
                sb.append(c);
                repeat--;
            }
            sb.append(c);
        }
    }
    return sb.toString();
    }
}

您需要一个堆栈来维护从最内层到最外层容器所需操作的内存

以下是Python中的代码:

def parenthesis_printer(s):
    L = [""]   # maintains the stack of the string-containers
    N = [1]    # maintains the stack of the print-multiplier needed for the corresponding string-container
    nstr = ""
    for i in range(len(s)):
        if s[i].isnumeric():
            nstr += s[i]
        elif s[i] == '(':
            nstr = "1" if len(nstr) == 0 else nstr
            nval = int(nstr)
            N.append(nval)
            L.append("")
            nstr = ""
        elif s[i] == ')':
            nval = N.pop()
            lval = L.pop()
            lstr = "".join([lval for _ in range(nval)])
            L[-1] += lstr
        else:
            L[-1] += s[i]
    return L[-1]

print(parenthesis_printer("3(b(2(c)))"))
输出:

bccbccbcc
3   0   [][]
(   3   [][]
b   0   [3][, ]
(   0   [3][, b]
2   0   [3, 1][, b, ]
(   2   [3, 1][, b, ]
c   0   [3, 1, 2][, b, , ]
)   0   [3, 1, 2][, b, , c]
)   0   [3, 1][, b, cc]
)   0   [3][, bcc]

这个问题自然是递归的。保留您已经开始的方法,您可以编写如下内容。在实际代码中,我可能倾向于一种分离标记化和解析的方法,这意味着我将执行两个单独的过程:第一个过程是将输入字符串转换为标记,第二个过程是从标记流生成输出

公共静态对求解(字符串s,int start){
int repeat=0;
字符串ret=“”;
对于(int i=start;i0){
ret+=内部第一;
}
repeat=0;//确保循环后面的'repeat'不是-1。
i=内秒;
}如果(c=='),则为else){
返回新的一对(ret,i);
}否则{
ret+=c;
}
}
返回新的一对(ret,s.length());
}
将此代码转换为使用单个
StringBuilder
——以避免冗余字符串副本——留作练习


上面使用了一个简单的
Pair
helper类。由于Java没有附带一个(groan),这里有一个非常简单的实现,可以与上面的代码一起使用;您还可以使用JavaFX的
JavaFX.util.Pair
java.util.AbstractMap.SimpleEntry
或其他任何东西

静态类对{
最后的T第一;
最后一秒;
成对(T、f、U、s){
第一个=f;
秒=秒;
}
}

与的答案基本相同,但使用java,并带有一点调试输出,以查看代码的行为:

public static String solve(String s)
{
    Stack<Integer> countStack = new Stack<>();   // stack for counting
    Stack<StringBuilder> stubs = new Stack<>();  // stack for parts of the string that were processed
    stubs.push(new StringBuilder());
    
    int count = 0;
    for(char c : s.toCharArray())
    {
        System.out.println(Character.toString(c) + "   " + count + "   " + countStack + stubs);
        
        if(Character.isDigit(c))
        {
            // part of a count (assumes digits are never part of the actual output-string)
            count = count * 10 + (c - '0');
        }
        else if(c == '(')
        {
            // encountered the start of a new repeated group
            if(count == 0)
                // no count specified, assume a count of one
                countStack.push(1);
            else
                // push the count for this group
                countStack.push(count);

            // push a new stringbuilder that will contain the new group
            stubs.push(new StringBuilder());
            count = 0;  // reset count
        }
        else if(c == ')')
        {
            // group terminated => repeat n times and append to new group one above
            String tmp = stubs.pop().toString();
            int ct = countStack.pop();
            
            for(int i = 0; i < ct; i++)
                stubs.peek().append(tmp);
        }
        else
        {
            // just a normal character, append to topmost group
            stubs.peek().append(c);
            count = 0;
        }
    }
    
    // if the string was valid there's only the output-string left on the stubs-list
    return stubs.peek().toString();
}
返回:

bccbccbcc


这里有点棘手的部分是找到匹配的论题。最简单的方法可能是使用多个过程,其中每个过程只替换在下一个结束过程之前没有开始过程的部分。当没有多余的偏执词时,或者您发现语法错误(例如,只剩下一个偏执词)时,您可以停止操作。括号前面的数字始终是一位数字,或者
12(b)
也是有效的输入吗?数字也可以出现在括号前面以外的地方;e、 g.
3(a4b)
?输入将仅由有效括号中的小写字母和数字(1到9)组成。最后一个右括号后面将没有字母或数字。仅就上下文而言,更一般的任务称为解析或构建or。这方面有一些库,但对于相对简单的语法来说,它们可能有些过头了。构建树结构可以让您在一次过程中完成这项工作。(你不需要准确地创建树,但它可以帮助你考虑递归的方法)。像你的第二个例子:
3(b(2(c))
=>
3(b(cc))
?这个想法很容易转移到Java。逻辑保持不变。是N和L字符串还是字符串数组?每个循环在哪里结束?N和L是堆栈。N维护数字乘法器,L维护相应容器中的字符串,因此堆栈代替了stringbuilder?我尝试使用导入,但它似乎给了我错误提示eclipse@rokkcrow什么错误?您是如何尝试使用它的?我复制了import和import javafx.util.Pair;在类之前,它给我错误,当我输入代码时,它不是一个导入options@rokkcrow再说一遍,什么错误?您使用的是什么Java版本?(JavaFX在Java11中被删除了,但是还有其他简单的方法来替换
类。)我正在使用EclipseIDE以这种方式创建大量新的字符串生成器是cargo cult编程;它实际上比使用字符串连接效率低。好的。我尝试了这个方法,但在这个例子中预期:但是是:有没有一种方法可以不删除[]的内容,我想它是从您使用的pop函数中删除的呢given:4(1(5b(n(j)))输出:bnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjbnjj]@Paul checkplease@KonradRudolph那么像往常一样,,该代码旨在演示一个原则,而不是最有效的解决方案。有很多地方可以对其进行优化,但至少IMO的可读性优于性能