0

网上关于“在二叉树中查找最小共同祖先”的许多答案及其补充问题“查找 2 个节点之间的距离”有 4 个问题:

  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);
    }
4

1 回答 1

0

该算法似乎是(没有将其完全分开)详尽地遍历整个树,直到找到一个节点,其中一个节点位于左侧,一个位于右侧。并随时创建一个额外的集合。

这里的问题似乎是你的算法效率很低。如果几乎从未执行此特定操作,那可能符合您的要求。但通常你可以做得更好。

于 2013-09-16T02:59:12.613 回答