【问题标题】:BST - counting nodes with left and right childrenBST - 计算具有左右子节点的节点
【发布时间】:2023-03-15 20:08:01
【问题描述】:

如标题所述,我试图通过仅计算 BST 中同时具有左右子节点的节点来解决此问题。我正在努力思考解决这个问题的逻辑。

我想到了这样的事情。

首先,检查根是否为空,或者它是否有任何空子。接下来,向右遍历树并继续检查孩子,当条件满足时增加一个计数器。但是当我到达结束节点并需要返回一个有左孩子要遍历的节点时会发生什么?我有一个临时节点来跟踪最近的父节点,但是当我需要上一层以上时怎么办?我假设这个问题的答案是递归解决它,但我什至不知道从哪里开始。

这是我所拥有的:

public int fullNodes() {
    int count = 0;
    Node n = root;
    Node temp = null;

    if (n == null || n.left == null && n.right == null) return count;

    count++; //increment count, since the root has children on both sides

    temp = n; //hold the previous place
    n = n.right; //go right

    //Now what?

    return count;
}

我在解决问题时仍然在努力递归思考,除了我的问题,你是如何学会递归思考的?只是大量的练习,还是有一些技巧和技巧可以用来解决问题?

【问题讨论】:

  • 假设你有一棵二叉树,你想回答这个问题,“有多少个节点同时有左右孩子?”假设您已经知道左子树的答案(如果有的话),并且您已经知道右子树的答案(如果有的话)。如果您知道这两个答案,那么您将如何计算整棵树的答案?只关注这一点,不要担心你将如何遍历树。这就是您可以递归地考虑它的方式。
  • nodesWithLeftAndRight(node):如果节点为空,则结果为零。否则,结果为 nodeWithLeftAndRight(left node) + nodeWithLeftAndRight(right node) + (1 if left node and right node is not null, else 0)

标签: java recursion binary-search-tree


【解决方案1】:

而不是使用临时变量来保存前一个节点——这仅适用于深度 1——在子节点上调用相同的函数

递归树遍历可能看起来像这样:

public int countSomething (Node node) {

    // Self;
    //   
    int result = 1;   // use your required logic here

    // Children;
    //    
    if (node.left != null)
        result += countSomething( node.left);
    if (node.right != null)
        result += countSomething( node.right);

    // done.
    return result;
}


// example usages
int treeTotal = countSomething( rootNode);
int subtreeTotal = countSomething( subtree);

然后,执行调用堆栈将保存函数的递归调用,每个调用都有其适当的上下文。当顶级调用返回时,它将对调用它的整个树/或子树的答案求和。

为您的 BST“节点同时具有左右子节点”放入适当的逻辑,而不是常量 1。

【讨论】:

  • 这是否考虑到节点必须同时具有左右子节点才能使计数上升?如果有,在哪里?我对这里发生的事情有点困惑。
  • @23k 这个方法说明了递归,但我不想为你做所有的工作。正如它所说,无论是在代码中还是在答案中,您都应该将所需的每个节点规则放入其中。
  • 当然不是,我只是对您的代码和 cmets 所做的事情感到非常困惑。也许这很明显,但我似乎错过了它。
  • 为每个节点“本身”计数 1 计算树或子树中的节点总数。如果您只想计算满足某些条件的节点,则如果满足该条件,则计为 1,否则计为 0;在添加左右子小计之前。
【解决方案2】:

首先让我们创建 Node 类的表示

class Node {
    public Node left;
    public Node right;
    public Node(){}
    public Node(Node left, Node right) {
        this.left = left;
        this.right = right;
    }
}

然后我们编写我们的 recusive 函数和使用你的函数的客户端

public class Main {   

    public static int countNodes(Node root) {
        if(root!=null && root.left!=null && root.right!=null) {
            return 1+countNodes(root.left)+countNodes(root.right);
        }
        return 0;
    }

    public static void main(String[] args) {
        Node right = new Node();
        Node left = new Node();
        Node root = new Node(left, right);
        root.right = new Node(new Node(), new Node());
        System.out.println(countNodes(root));
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2020-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多