簡體   English   中英

在二叉樹中找到兩個節點之間的距離

[英]Find distance between two nodes in binary tree

在網上有很多關於“在二叉樹中找到最小公祖”的答案,以及它的補充問題“在兩個節點之間查找距離”有四個問題:

  1. 不考慮重復
  2. 不考慮輸入節點是否無效/不存在/不在樹中
  3. 使用額外/輔助存儲
  4. 盡管獲得了答案,但不截斷遍歷。

我編寫了此示例代碼,以克服所有障礙。 但是由於我沒有在這個方向上找到“一個”答案,因此,如果我的代碼具有明顯的劣勢而我想念的話,我將不勝感激。 也許沒有。 額外的眼球表示贊賞。

  public int distance(int n1, int n2) {        
        LCAData lcaData = new LCAData(null, 0, 0);

        int distance = foundDistance (root, lcaData, n1,  n2, new HashSet<Integer>());

        if (lcaData.lca != null) {
            return distance;
        } else {
            throw new IllegalArgumentException("The tree does not contain either one or more of input data. ");
        }
    }

  private static class LCAData {
        TreeNode lca;
        int count;

        public LCAData(TreeNode parent, int count) {
            this.lca = parent;
            this.count = count;

        }
    }

 private int foundDistance (TreeNode node, LCAData lcaData, int n1, int n2, Set<Integer> set) {
        assert set != null;

        if (node == null) {
            return 0;
        }

        // when both were found
        if (lcaData.count == 2) {
            return 0;
        }

        // when only one of them is found
        if ((node.item == n1 || node.item == n2) && lcaData.count == 1) {
            // second element to be found is not a duplicate node of the tree.
            if (!set.contains(node.item)) {
                lcaData.count++;
                return 1;
            }
        }

        int foundInCurrent = 0;  
        // when nothing was found (count == 0), or a duplicate tree node was found (count == 1)
        if (node.item == n1 || node.item == n2) {
            if (!set.contains(node.item)) {
                set.add(node.item);
                lcaData.count++;
            }
            // replace the old found node with new found node, in case of duplicate. this makes distance the shortest.
            foundInCurrent = 1;
        }

        int foundInLeft = foundDistance(node.left, lcaData, n1, n2, set);
        int foundInRight = foundDistance(node.right, lcaData, n1, n2, set);

        // second node was child of current, or both nodes were children of current
        if (((foundInLeft > 0 && foundInRight > 0) || 
                (foundInCurrent == 1 && foundInRight > 0) || 
                    (foundInCurrent == 1 && foundInLeft > 0)) &&
                        lcaData.lca == null) {
            // least common ancestor has been obtained
            lcaData.lca = node;
            return foundInLeft + foundInRight; 
        }

        // first node to match is the current node. none of its children are part of second node.
        if (foundInCurrent == 1) {
            return foundInCurrent;
        }

        // ancestor has been obtained, aka distance has been found. simply return the distance obtained
        if (lcaData.lca != null) {
            return foundInLeft + foundInRight;
        } 

        // one of the children of current node was a possible match.
        return (foundInLeft + foundInRight) > 0 ? (foundInLeft + foundInRight) + 1 : (foundInLeft + foundInRight);
    }

該算法似乎是(沒有將其完全拉開)詳盡遍歷整個樹,直到找到一個節點,在該節點的左側找到一個節點,在右側找到一個節點。 並隨時創建其他集。

這里的問題似乎是您的算法效率很低。 如果幾乎從未執行過此特定操作,則這可能滿足您的要求。 但是通常您可以做得更好。

暫無
暫無

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

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