【问题标题】:How to fix a recursive string check如何修复递归字符串检查
【发布时间】:2018-09-05 15:50:13
【问题描述】:

在第一行输入会有秘密信息(数字序列)。例如1122

在第二个输入行将有用于以给定格式对消息进行编码的密码: “{LetterX}{CodeForX}{LetterY}{CodeForY}…” 原始消息中的每个 LetterX 都将在密码中使用 CodeForX 进行编码。例如A1B12C11D2

打印可以编码为给定密码的所有可能的原始消息的数量。在接下来的几行中,打印这些消息。 例如 3 -> AADD ABD CDD

我的想法是检查消息中是否存在字符串开头的任何字母代码(例如“1”、“12”等),如果找到,则将其从其中删除并递归处理直到结束到达字符串的长度。

public class Main {
static List<String> gList = new ArrayList<>();

public static void main(String[] args) throws IOException {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    String message = in.readLine();     // "1122"
    String codeStr = in.readLine();     // "A1B12C11D2"
// SPLITTING LETTERS FROM CODES:
    String [] secretCode = codeStr.split("[^A-Z0-9]+|(?<=[A-Z])(?=[0-9])|(?<=[0-9])(?=[A-Z])");
    int n = secretCode.length / 2;
    String [] letters = new String [n];  // [A  B   C   D]
    String [] codes = new String [n];    // [1  12  11  2]
    for (int i = 0; i < 2 * n; i+=2) {
        letters[i/2] = secretCode[i];
        codes[i/2] = secretCode[i+1];
    }
    CodesCheck(message, letters, codes);
    System.out.println(Arrays.toString(gList.toArray()));
}
static void CodesCheck (String message, String[] letters, String[] codes) {
    for (int i = 0; i < codes.length; i++) {
        if (codes[i].length() <= message.length() && 
            codes[i].equals(message.substring(0, codes[i].length()))) {
            gList.add(letters[i]);
            String newMessage = message.substring(codes[i].length());
            if (newMessage.equals("")) {
                gList.add("|");
                return;
            }
            CodesCheck(newMessage, letters, codes);
        }
    }
}
}

运行上面的代码时,我得到: [A, A, D, D, |, B, D, |, C, D, D, |] -> 所以在第二条消息中缺少“A”字母。 当我调试时,我可以看到递归函数以某种方式以“122”而不是“1122”进行。

【问题讨论】:

  • 为了完整起见,使用 HashMap(A -> 12 等)和一组字符串来保存结果的固定代码。以及适当的回溯:pastebin.com/B04Gw73H

标签: java string recursion


【解决方案1】:

那是因为你的递归是这样工作的:

 * CodesCheck with "1122" and i=0 adds A, then calls itself with "122"
 ** CodesCheck with "122" and i=0 adds A, then calls itself with "22"
 *** CodesCheck with "22" and i=3 adds D, then calls itself with "2"
 **** CodesCheck with "2" and i=3 adds D, then adds | and returns because next message is ""
 *** CodesCheck with "22" returns because i > 3
 ** CodesCheck with "122" continues with i=1, adds B, then calls itself with "2"
 *** CodesCheck with "2" and i=3 adds D, then adds | and returns because next message is ""
 ** CodesCheck with "122" continues with i=2, finds nothing, continues with i=3, finds nothing, returns because i>3
 * CodesCheck with "1122" and i=1 finds nothing, continues with i=2, adds C, calls itself with "22"
 ** CodesCheck with "22" and i=3 adds D, then calls itself with "2"
 *** CodesCheck with "2" and i=3 adds D, then adds | and returns because next message is ""
 ** CodesCheck with "22" returns because i > 3
 * CodesCheck with "1122" continues with i=3, finds nothing, then returns because i > 3

要解决此问题,您需要以某种方式跟踪递归调用,这意味着当处理"122" 的方法继续使用i=1B 时,您需要知道之前有一个A 和您需要在 B 之前将其添加到您的列表中。

一种方法是使用stack

void CodesCheck (String message, String[] letters, String[] codes, Stack<String> stack) {

当你调用你的方法时,只需为它提供一个空栈

CodesCheck(message, letters, codes, new Stack<String>());

然后不是直接将字母添加到gList,而是将它们添加到 stack 并确保在离开当前递归或迭代分支后 pop 本地字母:

stack.add(letters[i]);
final String newMessage = message.substring(codes[i].length());
if (newMessage.equals("")) {
    gList.addAll(stack);
    gList.add("|");
    stack.pop();
    return;
}
CodesCheck(newMessage, letters, codes, stack);
stack.pop();

【讨论】:

  • 堆栈在这里运行良好,如果您在每个步骤中复制列表并预先添加当前字符串,它也可以工作。 Stack的好处是性能更好,复制的好处是没有副作用(意味着不需要做pop)。
【解决方案2】:

问题不在于函数,而在于输出:

使用 A,您有多种可能性,您的程序会打印:

A [ output of recursive call with second letter A | ] [ output of recursive call with second letter B |].

您应该做的是让每个调用都返回结果 gLists(多个),并在调用函数前面加上它们当前的字母。到底应该放|介于两者之间。

【讨论】:

  • 是的,这就是我最初的想法——使用列表列表,但我不确定如何实现它。
猜你喜欢
  • 2017-04-06
  • 2013-02-02
  • 1970-01-01
  • 2013-02-10
  • 1970-01-01
  • 1970-01-01
  • 2016-01-27
  • 2022-01-09
  • 2016-10-02
相关资源
最近更新 更多