在第一个输入行,将有秘密消息(数字序列)。例如 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, |]
- &gt;所以在第二条消息中缺少“A”字母。
当我调试时,我可以看到递归函数以某种方式进行“122”而不是“1122”。
答案 0 :(得分: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=1
和B
时,您需要知道有之前需要A
,您需要在B
之前将其添加到列表中。
执行此操作的一种方法是使用stack
:
void CodesCheck (String message, String[] letters, String[] codes, Stack<String> stack) {
当您调用方法时,只需为其提供空堆栈:
CodesCheck(message, letters, codes, new Stack<String>());
然后,不是直接向gList
添加字母,而是将它们添加到堆栈,并确保在离开当前递归后,弹出本地字母或迭代分支:
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();
答案 1 :(得分:0)
问题不在于功能,而在于输出:
使用A,您有多种可能性,您的程序将打印出来:
A [ output of recursive call with second letter A | ] [ output of recursive call with second letter B |].
你应该做的是让每个调用返回结果gLists(多个),并且调用函数在它们当前字母前面加上。只有到底你应该把|介于两者之间。