所以我想出了一个有趣的问题,看看是否有一种有效的解决方法。所以基本上有一个平衡的二叉树,其中保存了id号(它不是bst所以没有正式的安排)。您有大量的查询来查找有多少节点。保证对于每个节点E,左子树将具有与该节点E上的右子树一样多或多一个节点。请求程序找出有多少节点的最佳方式是什么? 例如,给出这样的树:
1
4 2
3
该程序将提供以下输出:
Query: 1
Response: 4 2
Query: 4
Response 3
Query: 3
Response: 0 0
Query: 2
Response: 0 0
Answer: 4
答案 0 :(得分:1)
我终于把它弄糊涂了。
从条件
保证对于每个节点E,左子树将具有比该节点E处的右子树多或多一个节点。
紧随其后
所以,利用3:假设我们有一个(子)树T.我们知道它左边子树中叶子节点的数量是n left 。因此,我们知道右子树中的叶节点数是n left 或n left - 1,特别是它最多n left 子>
我们进入正确的子树。知道了这个子树中叶子节点的最大数量,并且知道它们在两侧的子树中均匀分开,我们可以推断出两件事:
这解决了事情的核心;剩下的就是简单的递归。在C ++中:
#include <cstddef>
// I'm using a simple node structure, you'd use query functions. The
// algorithm is not meaningfully altered by this.
struct node {
node *left = nullptr, *right = nullptr;
};
struct node_counter {
std::size_t leaf; // number of leaf nodes,
std::size_t trunk; // number of trunk nodes,
std::size_t depth; // and depth of the inspected subtree.
};
// Interesting function #1: Given a right subtree and the leaf-count and
// depth of its left sibling, find the node that might or might not be there
node const *find_leaf(node const *branch, std::size_t leaf_count, std::size_t depth) {
// We've gone down, found the slot. Return it.
if(depth == 0) { return branch; }
// The heart of the matter: Step into the subtree that contains the
// questionable slot, with its maximum leaf node count and depth.
return find_leaf(leaf_count % 2 ? branch->left : branch->right,
(leaf_count + 1) / 2, // int division
depth - 1);
}
// Recursive counter. This steps down on the left side, then infers the
// number of leaf and trunk nodes on the right side for each level.
node_counter count_nodes_aux(node const *root) {
// leftmost leaf node is reached. Return info for it.
if(!root->left) {
return { 1, 0, 0 };
}
// We're in the middle of the tree. Get the counts for the left side,
auto ctr_left = count_nodes_aux(root->left);
// then find the questionable slot on the right
auto leaf_right = find_leaf(root->right, ctr_left.leaf, ctr_left.depth);
return {
// the number of leaf nodes in this tree is double that of the left
// subtree if the node is there, one less otherwise.
ctr_left.leaf * 2 - (leaf_right ? 0 : 1),
// And this is just an easy way to keep count of the number of non-leaf
// nodes and the depth of the inspected subtree.
ctr_left.trunk * 2 + 1,
ctr_left.depth + 1
};
}
// Frontend function to make the whole thing easily usable.
std::size_t count_nodes(node const *root) {
auto ctr = count_nodes_aux(root);
return ctr.leaf + ctr.trunk;
}
为了尝试这一点,我使用了以下非常难看的main
函数,它只构建一个包含许多节点的树,在正确的位置插入新的并检查计数器是否以正确的方式移动。它不漂亮,它不遵循最佳实践,如果你在生产中编写这样的代码,你应该被解雇。这是它的方式,因为这个答案的要点是上面的算法,我没有看到任何使这个漂亮的感觉。
void fill_node(node *n) {
n->left = new node;
n->right = new node;
}
int main() {
node *root = new node;
fill_node(root);
fill_node(root->left);
fill_node(root->right);
fill_node(root->left->left);
fill_node(root->left->right);
fill_node(root->right->left);
fill_node(root->right->right);
fill_node(root->left->left->left);
fill_node(root->left->left->right);
fill_node(root->left->right->left);
fill_node(root->left->right->right);
fill_node(root->right->left->left);
fill_node(root->right->left->right);
fill_node(root->right->right->left);
fill_node(root->right->right->right);
std::cout << count_nodes(root) << std::endl;
root->left ->left ->left ->left ->left = new node; std::cout << count_nodes(root) << std::endl;
root->right->left ->left ->left ->left = new node; std::cout << count_nodes(root) << std::endl;
root->left ->right->left ->left ->left = new node; std::cout << count_nodes(root) << std::endl;
root->right->right->left ->left ->left = new node; std::cout << count_nodes(root) << std::endl;
root->left ->left ->right->left ->left = new node; std::cout << count_nodes(root) << std::endl;
root->right->left ->right->left ->left = new node; std::cout << count_nodes(root) << std::endl;
root->left ->right->right->left ->left = new node; std::cout << count_nodes(root) << std::endl;
root->right->right->right->left ->left = new node; std::cout << count_nodes(root) << std::endl;
root->left ->left ->left ->right->left = new node; std::cout << count_nodes(root) << std::endl;
root->right->left ->left ->right->left = new node; std::cout << count_nodes(root) << std::endl;
root->left ->right->left ->right->left = new node; std::cout << count_nodes(root) << std::endl;
root->right->right->left ->right->left = new node; std::cout << count_nodes(root) << std::endl;
root->left ->left ->right->right->left = new node; std::cout << count_nodes(root) << std::endl;
root->right->left ->right->right->left = new node; std::cout << count_nodes(root) << std::endl;
root->left ->right->right->right->left = new node; std::cout << count_nodes(root) << std::endl;
root->right->right->right->right->left = new node; std::cout << count_nodes(root) << std::endl;
root->left ->left ->left ->left ->right = new node; std::cout << count_nodes(root) << std::endl;
root->right->left ->left ->left ->right = new node; std::cout << count_nodes(root) << std::endl;
root->left ->right->left ->left ->right = new node; std::cout << count_nodes(root) << std::endl;
root->right->right->left ->left ->right = new node; std::cout << count_nodes(root) << std::endl;
root->left ->left ->right->left ->right = new node; std::cout << count_nodes(root) << std::endl;
root->right->left ->right->left ->right = new node; std::cout << count_nodes(root) << std::endl;
root->left ->right->right->left ->right = new node; std::cout << count_nodes(root) << std::endl;
root->right->right->right->left ->right = new node; std::cout << count_nodes(root) << std::endl;
root->left ->left ->left ->right->right = new node; std::cout << count_nodes(root) << std::endl;
root->right->left ->left ->right->right = new node; std::cout << count_nodes(root) << std::endl;
root->left ->right->left ->right->right = new node; std::cout << count_nodes(root) << std::endl;
root->right->right->left ->right->right = new node; std::cout << count_nodes(root) << std::endl;
root->left ->left ->right->right->right = new node; std::cout << count_nodes(root) << std::endl;
root->right->left ->right->right->right = new node; std::cout << count_nodes(root) << std::endl;
root->left ->right->right->right->right = new node; std::cout << count_nodes(root) << std::endl;
root->right->right->right->right->right = new node; std::cout << count_nodes(root) << std::endl;
}
答案 1 :(得分:-1)
int countnodes(ele,count)
{
if(ele.right != null)
{
count += countnodes(ele.right,0);
}
if(ele.left != null)
{
count += countnodes(ele.left,0);
}
return count++; //got to count this node
}