簡體   English   中英

樹問題 - 了解何時實施迭代解決方案與何時實施遞歸解決方案

[英]Tree Problems - Understanding when to implement iterative solution v.s. when to implement recursive solution

我在空閑時間一直在研究算法問題,以此為明年夏天的暑期實習面試做准備。 我目前正在研究樹問題,我發現實際編碼對於大多數問題來說非常簡單,但我很難理解這些問題的復雜性。 我正在處理的一個問題是二叉樹預序遍歷,我以遞歸和迭代的方式實現了它。 但是,迭代解決方案要慢得多,我不明白為什么? 這是我的兩個解決方案:

迭代:

public List<Integer> preorder(TreeNode root) {
    List<Integer> ans = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<>();

    if (root == null) return ans;

    stack.push(root);

    while(!stack.isEmpty()) {
        TreeNode node = stack.pop();
        ans.add(node.val);

        if (node.right != null) stack.push(node.right);
        if (node.left != null) stack.push(node.left);
    {

    return ans;
}

遞歸:

public list<Integer> preorder(TreeNode root) {
    List<Integer> ans = new ArrayList<>();
    dfs(root, ans);
    return ans;
}

public void dfs (TreeNode root, List<Integer> ans) {
    if (root == null) return;
    ans.add(root.val);
    dfs(root.left);
    dfs(node.right)
}

據我所知,遞歸解決方案每次調用有兩個分支,如果平衡,樹的深度是 O(log n),但最壞的情況是 O(n),所以復雜度是 O(2^n )。 我可以完全離開,可能是。 迭代解決方案具有恆定的推送和彈出時間,所以我最初的直覺是它會是 O(n) 時間。 如果是這些情況,我看不出指數解決方案如何運行得更快。 如果有人可以幫助我理解此類問題的復雜性,將不勝感激。

在這兩種情況下,時間復雜度都是 O(n):您訪問每個節點一次並為每個節點執行恆定數量的工作(將值添加到ArrayListStack攤銷 O(1))。

您的迭代解決方案較慢的原因之一可能是使用Stack 這個 class 是同步的(它擴展了Vector )。 在這種情況下,您不需要線程安全,因此請考慮將其替換為ArrayDeque

Deque<Integer> stack = new ArrayDeque<Integer>();

在這兩種情況下,空間復雜度也是 O(n):迭代解決方案中的顯式堆棧和遞歸解決方案中的隱式調用堆棧可以增長到n (不平衡情況)。

具有恆定復雜性與指數的東西並不意味着它更快。 它只是說明了隨着輸入的增加它會變慢的速度。 我想說,對於面試和現實世界來說,這本身就是非常有價值的一課,因為具有最低 O-time 的解決方案通常不是“最好的”或更實用的。

除了復雜性之外,我可以看到基於堆棧的方法可能會更慢,因為它需要在stack上彈出和推送項目,而遞歸解決方案只需要調用 function。 如果不進行基准測試,我不能肯定地說。

暫無
暫無

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

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