首先,我想说我知道这是解决我问题的最糟糕的解决方案,但我只是想熟悉递归。我想检查序列是否是DNA(因此它只能包含A,T,G或C)。我的代码:
public Boolean check(String seq) {
System.out.println(seq);
Boolean correct = true;
Character letter = seq.charAt(seq.length() - 1);
if ("ATGC".contains(letter.toString())) {
if (seq.substring(0, seq.length() - 1).length() > 0) {
check(seq.substring(0, seq.length() - 1));
}
} else {
correct = false;
}
System.out.println(seq + " " + correct);
return correct;
}
但是,当我运行代码时,它会在更改correct = false
后继续运行。为了清楚起见,我将粘贴打印语句的输出:
ATXGCTGC
ATXGCTG
ATXGCT
ATXGC
ATXG
ATX
ATX false
ATXG true
ATXGC true
ATXGCT true
ATXGCTG true
ATXGCTGC true
返回的布尔值为true
,但代码应在ATX false
后停止。 出错了 如何解决此问题?
答案 0 :(得分:1)
没关系。你称之为“继续运行”的东西就是递归的工作方式。如果你看过可以帮助你作为隐喻的初始电影。
函数多次调用自身(你的第一个println
语句标记出来),然后一旦某个级别满足递归结束条件,函数就会将执行返回到调用堆栈帧(即捕获的内容)在你的第二个println
)。
使用更简单的“AA”示例:
P.S。你遇到的一个问题是你忽略了函数的返回结果。
答案 1 :(得分:1)
您放弃了对check
的递归调用的结果。因此,即使检查返回false
,信息也会丢失。由于调用check
的分支从不设置correct
,因此它将保留其初始化值(true
)。
据我所知,通过快速浏览,解决方案就像分配correct
check
的返回值一样简单。
答案 2 :(得分:1)
您没有检查它是否返回false
。当check()
返回false
答案 3 :(得分:1)
只需致电
check(seq.substring(0, seq.length() - 1));
你正在做你想做的事情,但是当递归返回时,该方法继续耗尽(正如你在输出中字符串“增长”时所看到的那样)。
如果你增加使用
return check(seq.substring(0, seq.length() - 1));
或者
correct = check(seq.substring(0, seq.length() - 1));
您可以获得所需的输出。您可以使用调试器来诊断哪一个更有意义
答案 4 :(得分:1)
遇到错误的字符时,没有条件终止。适当的递归方法如下:
private static Set<Character> LEGAL_CHARS =
new HashSet<>(Arrays.asList('A', 'T', 'G', 'C'));
public boolean check(String seq) {
if (seq.isEmpty()) {
return true;
}
if (!LEGAL_CHARS.contains(seq.charAt(0))) {
return false;
}
return check(seq.substring(1));
}
答案 5 :(得分:0)
您只需更改行
即可 if (seq.substring(0, seq.length() - 1).length() > 0) {
check(seq.substring(0, seq.length() - 1));
}
到
if (seq.substring(0, seq.length() - 1).length() > 0) {
return check(seq.substring(0, seq.length() - 1));
}
这会将您的检查结果返回给上层递归函数,
最终是期望的结果。
为什么我需要返回检查功能?
当您在if检查中调用check函数时,它会创建一个新的递归调用,该调用在堆栈中使用其变量排队。当它返回结果时,你只是忽略它(没有存储结果)。要使用最低级递归函数的值,您需要将其值传递回其父递归调用made.SO,最后得到结果。