我最近在一次采访中遇到了这个问题。原来的问题是
给定一个指向结构的指针(其结构可以指向二叉树或双向链表),编写一个函数,返回它是指向二叉树还是 DLL。结构定义如下
struct node
{
/*data member*/
node *l1;
node *l2;
};
我立即深入研究了这个问题,但后来我意识到这个问题存在一些歧义。如果指针不指向它们中的任何一个(即它是格式错误的 DLL 或格式错误的树)怎么办。所以面试官告诉我,然后我必须编写函数,以便它可以返回所有三种情况。所以函数的返回值变成了一个枚举形式
enum StatesOfRoot
{
TREE,
DLL,
INVALID_DATA_STRUCTURE, /* case of malformed dll or malformed tree */
EITHER_TREE_DLL, /* case when there is only 1 node */
};
所以问题归结为验证二叉树和 DLL 的属性。对于 DLL,这很容易。对于二叉树,我能想到的唯一验证是从根到节点的路径不应该超过一条。(或者不应该有任何循环)所以我建议我们进行深度优先搜索并继续跟踪访问过的节点节点使用 HashMap(面试官直接拒绝)或使用 BST 维护一组访问节点(我想使用 std::set 但面试官突然弹出另一个限制,我不能使用 STL)。他拒绝了这个想法说我不允许使用任何其他数据结构。然后我提出了龟兔问题的修改版本(将二叉树的每个分支视为一个单链表),他说这行不通。
问题的核心
然后面试官提出了他的解决方案。他说我们可以计算顶点数和边数,并断言关系顶点数=边数+1(必须为二叉树保留的属性)。令我困惑的是我们如何计算顶点的数量(不使用任何额外的数据结构)?他说可以通过简单地执行任何遍历(preorder,postorder,inorder)来完成。我质疑如果树中有一个循环,我们将如何防止无限循环,因为我们没有跟踪访问过的节点。他说这是可能的,但没有告诉怎么做。我严重怀疑他的做法。谁能提供一些关于他提出的解决方案是否正确的见解?如果是,您将如何明确维护不同顶点的计数?请注意,您传递的只是一个指针,您没有其他信息。
PS:后来我收到通知说我通过了下一轮,甚至没有回答面试官的最终解决方案。它应该是诡计吗?
编辑:
为了清楚起见,如果我们假设第三种情况不存在(即我们保证它是一个 dll 或二叉树),那么问题就很简单了。它是第三种情况的树部分让我发疯. 请在回答时注意这一点。