为什么这段代码会继续(递归)?

时间:2016-12-03 09:55:39

标签: java recursion return return-value

首先,我想说我知道这是解决我问题的最糟糕的解决方案,但我只是想熟悉递归。我想检查序列是否是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后停止。 出错了 如何解决此问题?

6 个答案:

答案 0 :(得分:1)

没关系。你称之为“继续运行”的东西就是递归的工作方式。如果你看过可以帮助你作为隐喻的初始电影。

函数多次调用自身(你的第一个println语句标记出来),然后一旦某个级别满足递归结束条件,函数就会将执行返回到调用堆栈帧(即捕获的内容)在你的第二个println)。

使用更简单的“AA”示例:

  1. check(“AA”)运行第一个println,然后运行check(“A”)
  2. check(“A”)也会先运行println,此时条件会阻止进一步的递归,所以执行进入第二个println语句
  3. 函数调用返回,现在我们在检查函数后回到我们的检查(“AA”)调用
  4. 执行继续,您会看到指向结果的第二个println
  5. P.S。你遇到的一个问题是你忽略了函数的返回结果。

答案 1 :(得分:1)

您放弃了对check的递归调用的结果。因此,即使检查返回false,信息也会丢失。由于调用check的分支从不设置correct,因此它将保留其初始化值(true)。

据我所知,通过快速浏览,解决方案就像分配correct check的返回值一样简单。

答案 2 :(得分:1)

您没有检查它是否返回false。当check()返回false

时,您需要创建一个if语句来结束方法

答案 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)

遇到错误的字符时,没有条件终止。适当的递归方法如下:

  1. 如果字符串为空 - 没关系
  2. 如果没有,请检查第一个字符:
    • 如果它不是“ATGC”字符之一,则返回false
    • 如果是,则从第二个字符开始在子字符串上递归应用算法:

  3. 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,最后得到结果。