こんにちは皆さん、私はコードの王様です。私は長年BATで技術的な研究開発に携わっています。暇な時間を使ってリートコードを再描画します。長年の実務経験を組み合わせてアルゴリズムをより明確に説明したいと思います。公開番号「コードランダムノート」に注目して、より多くのオリジナルの記事をお待ちしています。
再帰的アルゴリズムの時間の複雑さ
多くの学生は再帰的アルゴリズムの時間の複雑さについてあまり知らない
同じ問題、これも再帰アルゴリズムを使用して、一部の学生はO(n)コードを書き、一部の学生はO(logn)コードを書きました
これが、再帰の時間の複雑さを十分に理解していないことが原因である
あなたがいる場合、再帰的混乱の時間複雑に読者この記事を読んでいる、私はあなたが我慢して、オン読むことを願って、収穫しなければなりません
ここで、簡単なインタビューの質問を通して、再帰的アルゴリズムの時間の複雑さを徐々に分析し、最終的に最適なソリューションを見つけたいと思います。
面接官に聞く
このインタビューの質問を見てください:xのn乗を見つけてください
このような単純な質問コードの書き方を考えてください。
最も直感的な方法は、結果を見つけるためのforループである必要があります。コードは次のとおりです。
int function1(int x, int n) {
int result = 1; // 注意 任何数的0次方等于1
for (int i = 0; i < n; i++) {
result = result * x;
}
return result;
}
時間の複雑さはO(n)
インタビュアーの2番目の質問
この時点でインタビュアーは言うでしょう、より効率的なアルゴリズムはありますか?
現時点で生徒にアイデアがない場合は、言わないことをお勧めします。面接担当者と話し合うことができます。質問:ヒントを教えてください。
インタビュアーは通常プロンプトを出します:再帰的アルゴリズムを検討してください
一部の学生は、この問題を解決するために再帰を使用して、次のように再帰アルゴリズムを作成しました
int function2(int x, int n) {
if (n == 0) {
return 1; // return 1 同样是因为0次方是等于1的
}
return function2(x, n - 1) * x;
}
インタビュアーは尋ねました:このコードの時間の複雑さは何ですか?
一部の学生は再帰を見るとすぐにそれを考えるかもしれlogn
ませんが、これはそうではありません
再帰アルゴリズムの時間の複雑さは、本質的に次の要素に依存します:再帰の数*各再帰の操作の数
次に、もう一度コードを見てみましょう。何度か再帰しています。
n-1のたびに、時間の複雑度がn回再帰されO(n)
、乗算演算が実行されるたびに、乗算演算の時間の複雑度は定数項になります。O(1)
したがって、このコードの時間の複雑さは n * 1 = O(n)
この時間の複雑さは、面接担当者の期待に応えられない可能性があります。
インタビュアー3つの質問
したがって、クラスメートは次のような再帰的アルゴリズムのコードを記述して、xのn乗を求めます
int function3(int x, int n) {
if (n == 0) {
return 1;
}
if (n % 2 == 1) {
return function3(x, n/2) * function3(x, n/2)*x;
}
return function3(x, n/2) * function3(x, n/2);
}
インタビュアーはそれを見て、少し微笑んでコードの複雑さを尋ねました。
分析しましょう
まず、再帰の回数を見て、再帰の数を完全なバイナリツリーに抽象化できます。
先ほど書いたアルゴリズムは、図に示すように、完全なバイナリツリーで表現できます(便宜上、nを偶数にすることを選択しました)。
現在、この二分木はxがn乗され、nが16の場合です。
nが16の場合、乗算を何回実行しますか
このツリーの各ノードは、再帰と乗算演算を表します
したがって、再帰が何回行われるかは、このツリーにあるノードの数に依存します。
二分木に精通している学生は、二分木内のノード数を見つける方法を知っている必要があります
この完全なバイナリツリーのノード数は2^3 + 2^2 + 2^1 + 2^0 = 15
一部の学生は、これが実際には比例シーケンスの合計式であることを理解しますが、理解できない場合は、この結論を直接書き留めることができます。
この結論は、二分木に関するインタビューの質問によく出てきます。
したがって、xのn乗を求める場合、次の図に示すように、この再帰的ツリーにはノードがいくつありますか。
時間の複雑さの定数項を無視した-1
後、この再帰的アルゴリズムの時間の複雑さは依然としてO(n)であることがわかります。
このとき、インタビュアーは尋ねます、再帰アルゴリズムはまだ同じであるようですO(n)
、明らかにインタビュアーの期待に応えていません
インタビュアー4つの質問
次に考えるO(logn)
書き方をする必要があります再帰アルゴリズム
上記の再帰アルゴリズムのコードを思い出してください。冗長性はありますか?
この最適化された再帰アルゴリズムコードを見てください。
int function4(int x, int n) {
if (n == 0) {
return 1;
}
int t = function4(x, n/2);// 这里相对于function3,是把这个递归操作抽取出来
if (n % 2 == 1) {
return t*t*x;
}
return t*t;
}
時間の複雑さを見てみましょう
それでも彼が何回再帰したか見てください
再帰呼び出しが1つだけあり、そのたびにn / 2であることがわかります
したがって、ここでは、log 2をn回だけ呼び出してlogを呼び出します。
各再帰は定数演算でもある乗算演算であり、
したがって、この再帰的アルゴリズムの時間の複雑さは、実際のO(logn)です。
学生が最終的にそのようなコードを記述し、時間の複雑さの分析が非常に明確である場合、インタビュアーはより満足すると思います。
まとめ
最後に、このような簡単なインタビューの質問を通して、誰もが再帰アルゴリズムの時間の複雑さを分析する方法を本当に理解することを願っています。