私は最近のインタビューでこの質問に直面しました。元の質問は
構造体 (バイナリ ツリーまたは双方向リンク リストのいずれかを指すことができるように構造化されている) へのポインターが与えられた場合、それがバイナリ ツリーまたは DLL のどちらを指しているかを返す関数を記述します。構造体は次のように定義されます。
struct node
{
/*data member*/
node *l1;
node *l2;
};
私はすぐに問題に飛び込みましたが、問題にはあいまいさがあることに気付きました。ポインタがそれらのいずれも指していない場合 (つまり、不正な形式の DLL または不正なツリーです)。そのため、インタビュアーは、3 つのケースすべてを返すことができるように関数を作成する必要があると私に言いました。したがって、関数の戻り値は次の形式の列挙型になります
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: その後、面接官に最終的な解決策を答えることなく、次のラウンドに進むという通知を受け取りました。トリックラウンドのはずだった?
編集:
明確にするために、3番目のケースが存在しないと仮定した場合(つまり、dllまたはバイナリツリーであることが保証されている場合)、問題は非常に簡単です.3番目のケースのツリー部分が私を夢中にさせています. . この点に注意して回答してください。