在二叉树中查找两个节点之间的距离

时间:2013-09-16 02:33:27

标签: java tree least-common-ancestor

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

  1. 不考虑重复
  2. 不考虑输入节点是否无效/不在树中
  3. 使用额外/辅助存储
  4. 虽然获得了答案,但没有截断遍历。
  5. 我编写了这个样本以克服所有障碍。但由于我没有找到这方面的“单一”答案,如果我的代码有一个我缺少的重大缺点,我将不胜感激。也许没有。额外的眼球赞赏。

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

1 个答案:

答案 0 :(得分:0)

该算法似乎是(完全不将它拉开)以彻底遍历整个树,直到找到一个节点,其中左侧有一个节点,右侧有一个节点。并随时创建一个额外的集合。

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