【问题标题】:Count number of left nodes in BST计算 BST 中的左节点数
【发布时间】:2021-04-20 02:26:36
【问题描述】:

给定一个 BST,我需要找到树的左节点数。

示例:`

          +---+
          | 3 |
          +---+
         /     \
     +---+     +---+
     | 5 |     | 2 |
     +---+     +---+
    /         /     \
+---+     +---+     +---+
| 1 |     | 4 |     | 6 |
+---+     +---+     +---+
         /
     +---+
     | 7 |
     +---+`

答案应该是 4,因为 (5, 1 , 4, 7) 都是树的左节点。

我想做的是:

public int countLeftNodes() {
    return countLeftNodes(overallRoot, 0);
}

private int countLeftNodes(IntTreeNode overallRoot, int count) {
    if (overallRoot != null) {
        count += countLeftNodes(overallRoot.left, count++);    
        count = countLeftNodes(overallRoot.right, count);
    }
    return count;
}

我知道这是错的,但我不知道为什么。谁能解释一下原因,也可以帮我解答一下。

【问题讨论】:

    标签: binary-tree


    【解决方案1】:

    第二个递归分支覆盖第一个递归分支的值。此外,您应该为左根添加 1。

    类似:

    private int countLeftNodes(IntTreeNode node) {
        int count = 0;
        if (node.left != null) 
            count += 1 + countLeftNodes(node.left);    
    
        if (node.right != null)
            count += countLeftNodes(node.right);
    
    
        return count;
    }
    

    【讨论】:

      【解决方案2】:

      无需在调用堆栈中向下传播累加器(count 参数),因为您不依赖尾递归。

      public int countLeftNodes(IntTreeNode node) {
          // This test is only needed if the root node can be null.
          if (node == null) return 0;
      
          int count = 0;
          if (node.left != null) {
              count += 1 + countLeftNodes(node.left);
          }
          if (node.right != null) {
              count += countLeftNodes(node.right);
          }
          return count;
      }
      

      【讨论】:

        【解决方案3】:

        在这里的第二行

        count += countLeftNodes(overallRoot.left, count++);    
        count = countLeftNodes(overallRoot.right, count);
        

        你丢弃了之前的 count 值。也许应该是+= 而不是=

        不过我会这样表达:

        private int countLeftNodes(IntTreeNode root) {
            return (root.left  == null ? 0 : countLeftNodes(root.left) + 1) +
                   (root.right == null ? 0 : countLeftNodes(root.right));
        }
        

        【讨论】:

          【解决方案4】:

          我认为您必须稍微重构一下您的代码。而不是传递左节点的当前计数,只需从两个子节点接收它并将它们相加即可。

          【讨论】:

            【解决方案5】:

            我认为最优雅的解决方案是这个。是的,我当然有偏见。我是人类:-)

            def countLeft (node,ind):
                if node == null: return 0
                return ind + countLeft (node->left, 1) + countLeft (node->right, 0)
            
            total = countLeft (root, 0)
            

            通过向下传递左侧节点的指示符,它简化了必须向上传递的内容。下图显示了向上传递的每个总和 - 您从底部开始,每个 null 向上传递 0。

            左边的每个节点都向上传递 1 加上来自下面两个分支的任何值。右边的每个节点都向上传递 0 加上来自下面两个分支的任何值。

            根不添加任何内容,因为它既不是左节点也不是右节点(它被视为与右节点相同)。

                                    4
                                    ^
                                    |
                                  +---+
                                  | 3 |
                        __________+---+__________
                       /2                       2\
                  +---+                           +---+
                  | 5 |                           | 2 |
                  +---+                           +---+
                 /1                              /2   0\
             +---+                          +---+       +---+
             | 1 |                          | 4 |       | 6 |
             +---+                          +---+       +---+
            /0   0\                        /1   0\     /0   0\
                                      +---+
                                      | 7 |
                                      +---+
                                     /0   0\
            

            你可以从这个完整的程序中看到操作:

            #include <stdio.h>
            
            typedef struct sNode { int val; struct sNode *left, *right; } tNode;
            
            #define setNode(N,V,L,R) N.val = V; N.left = L; N.right = R
            
            int countLeft (tNode *node, int ind) {
                if (node == NULL) return 0;
                int x = ind + countLeft (node->left, 1) + countLeft (node->right, 0);
                printf ("Node %d passing up %d\n", node->val, x);
                return x;
            }
            
            int main (void) {
                tNode n3, n5, n1, n2, n4, n6, n7;
                setNode (n3, 3, &n5, &n2);
                setNode (n5, 5, &n1, NULL);
                setNode (n1, 1, NULL, NULL);
                setNode (n2, 2, &n4, &n6);
                setNode (n4, 4, &n7, NULL);
                setNode (n7, 7, NULL, NULL);
                setNode (n6, 6, NULL, NULL);
            
                printf ("countLeft is %d\n", countLeft (&n3, 0));
                return 0;
            }
            

            输出调试行:

            Node 1 passing up 1
            Node 5 passing up 2
            Node 7 passing up 1
            Node 4 passing up 2
            Node 6 passing up 0
            Node 2 passing up 2
            Node 3 passing up 4
            countLeft is 4
            

            countLeft 函数的非调试版本就像这个答案开头的伪代码一样简单:

            int countLeft (tNode *node, int ind) {
                if (node == NULL) return 0;
                return ind + countLeft (node->left, 1) + countLeft (node->right, 0);
            }
            

            【讨论】:

            • @Catie:不,因为它做的第一件事是检查空值,然后在这种情况下返回 0。这是执行此操作的标准方法,因此您不必将根节点视为特殊节点。
            【解决方案6】:

            计算左节点的函数(仅具有左子节点: 您可以使用递归方法做什么,如果只存在左孩子,则返回 1。

                int count_left_nodes(tree_type* root)
                 {
            
                 if(root == NULL)       
                    return 0;
                 if(root->left != NULL && root->right==NULL)      
                    return 1;            
                 else 
                    return count_left_nodes(root->left)+
                        count_left_nodes(root->right); 
            
                 }
            

            【讨论】:

              猜你喜欢
              • 2023-03-15
              • 1970-01-01
              • 1970-01-01
              • 2017-08-22
              • 1970-01-01
              • 2020-03-18
              • 2021-10-17
              • 2021-09-03
              • 1970-01-01
              相关资源
              最近更新 更多