簡體   English   中英

return 語句在遞歸 function 中究竟是如何工作的?

[英]How exactly does return statement work in recursive function?

我很難解決任何二叉樹問題,而且大多數問題都是遞歸的,所以我決定繞道而行,重新從基礎開始。 這基本上是預序遍歷列表。 如果至少有 1 個節點,我已經確定了兩種可以給我正確結果的方法,但我不確定這兩者之間的內在差異。 可以看到,一個遇到null返回列表,另一個遇到null返回null:

public List<Integer> getList1(TreeNode root) {
    return getList1Helper(root, new ArrayList<>());
}

private List<Integer> getList1Helper(TreeNode root, List<Integer> list) {
    if (root == null) {
        return list;
    }
    list.add(root.val);
    getList1Helper(root.left, list);
    getList1Helper(root.right, list);
    return list;
}

public List<Integer> getList2(TreeNode root) {
    return getList2Helper(root, new ArrayList<>());
}

private List<Integer> getList2Helper(TreeNode root, List<Integer> list) {
    if (root == null) {
        return null; // difference denoted *
    }
    list.add(root.val);
    getList2Helper(root.left, list);
    getList2Helper(root.right, list);
    return list;
}

有人對此有任何想法嗎? 另外,為什么 function 在命中第一個 null 時不返回列表並停止所有遞歸?

盡管您在兩個版本的代碼中返回的內容不同,但兩個輔助函數實際上都沒有使用從遞歸調用返回的值:

getList2Helper(root.left, list);

上面進行了遞歸調用,它返回了一些東西,但是調用者沒有對它做任何事情。

返回值唯一不同的時候是基本情況開始時。這意味着當初始調用者將null作為第一個參數(表示一棵空樹)傳遞時,它們會有所不同。 第一個版本將返回一個空數組列表,而第二個版本將返回null 所以它們並不完全等價。 返回數組列表的那個將更多是我期望為空樹返回的(即空數組列表,而不是null )。

打掃干凈

由於助手 function 實際上填充了作為參數給出的數組列表,因此它不需要返回任何內容。 main function 可以創建數組列表,將其傳遞給助手(不返回任何內容),然后返回填充的列表。

像這樣:

public List<Integer> getList(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    getListHelper(root, list);
    return list;
}

private void getListHelper(TreeNode root, List<Integer> list) {
    if (root == null) {
        return;
    }
    list.add(root.val);
    getListHelper(root.left, list);
    getListHelper(root.right, list);
}

選擇

您可以完全避免使用幫助程序 function(及其第二個參數),而是從遞歸調用返回的列表中填充本地數組列表:

public List<Integer> getList(TreeNode root) {
    List<Integer> list = new ArrayList<>();
    if (root != null) {
        list.add(root.val);
        list.addAll(getList(root.left));
        list.addAll(getList(root.right));
    }
    return list;
}

這樣效率較低,因為值會多次從一個列表復制到另一個列表。 使用允許在 O(1) 時間內連接列表的鏈表實現,您可以克服這個缺點。

在輔助函數中返回什么並不重要,因為您從不使用返回值。 您也可以將方法定義為 void 並仍然獲得正確的結果。
本質上,您正在做的(正確的)只是傳遞列表的引用。

對於你的第二個問題:假設你在二叉樹中找到一個 null 節點向下三層。 當您返回該級別時,您將返回到該二叉樹中的第二級,那里還有其他 getListHelper 調用正在等待發生。 只有當每個節點都已被訪問時,第一個getListHelper 調用才會將列表返回給 getList 方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM