O(n!)
関数の例(コード内)とは何ですか? n
を参照して実行するには、適切な数の操作が必要です。つまり、時間の複雑さについて尋ねています。
行くぞこれは、おそらくO(n!)
時間(n
は関数の引数です)で実行される関数の最も単純な例です。
void nFacRuntimeFunc(int n) {
for(int i=0; i<n; i++) {
nFacRuntimeFunc(n-1);
}
}
古典的な例の1つは、ブルートフォース検索による 巡回セールスマン問題 です。
N
都市がある場合、ブルートフォースメソッドは、これらのN
都市のすべての順列を試行して、最も安い都市を見つけます。 N
cityの順列の数は_N!
_であるため、複雑さの要因となります(O(N!)
)。
Big O Wikipedia の記事の 共通機能の順序 セクションを参照してください。
記事によると、ブルートフォース検索で 巡回セールスマン問題 を解き、 決定子 を 未成年者による拡大 で見つけることは両方ともO(n! )。
問題があります。NP-complete
(非決定的な多項式時間で検証可能)。入力がスケールする場合、つまり、問題を解決するために必要な計算が大幅に増えます。
一部NP-hard
問題: ハミルトニアンパス問題 ( open img )、 旅行セールスマン問題 ( 開くimg )
一部NP-complete
問題: ブール充足可能性問題(土) ( open img )、 N-パズル ( open img )、 ナップザック問題 ( open img )、 サブグラフ同型問題 ( open img )、 サブセット和問題 ( open img )、 クリーク問題 ( open img )、- 頂点カバー問題 ( open img )、 独立セット問題 ( open img )、 セット問題の支配 ( imgを開く )、 グラフの色付けの問題 ( imgを開く )、
出典: link
未成年者による展開で行列式を見つける。
非常に良い説明 ここ 。
# include <cppad/cppad.hpp>
# include <cppad/speed/det_by_minor.hpp>
bool det_by_minor()
{ bool ok = true;
// dimension of the matrix
size_t n = 3;
// construct the determinat object
CppAD::det_by_minor<double> Det(n);
double a[] = {
1., 2., 3., // a[0] a[1] a[2]
3., 2., 1., // a[3] a[4] a[5]
2., 1., 2. // a[6] a[7] a[8]
};
CPPAD_TEST_VECTOR<double> A(9);
size_t i;
for(i = 0; i < 9; i++)
A[i] = a[i];
// evaluate the determinant
double det = Det(A);
double check;
check = a[0]*(a[4]*a[8] - a[5]*a[7])
- a[1]*(a[3]*a[8] - a[5]*a[6])
+ a[2]*(a[3]*a[7] - a[4]*a[6]);
ok = det == check;
return ok;
}
特定の配列のすべての順列を計算するアルゴリズムは、O(N!)
です。
私は少し遅れていると思うが、 snailsort はO(n!)決定論的アルゴリズムの最良の例であると思う。基本的に、並べ替えるまで、配列の次の順列を見つけます。
次のようになります。
template <class Iter>
void snail_sort(Iter first, Iter last)
{
while (next_permutation(first, last)) {}
}
最も簡単な例:)
擬似コード:
input N
calculate N! and store the value in a vaiable NFac - this operation is o(N)
loop from 1 to NFac and output the letter 'z' - this is O(N!)
そこに行きます:)
実際の例として-アイテムのセットのすべての順列を生成するのはどうですか?
printf("Hello World");
はい、これはO(n!)です。そうでないと思われる場合は、BigOhの定義を読むことをお勧めします。
この答えを追加したのは、人々が実際に何を意味しているかに関係なく、常にBigOhを使用しなければならない迷惑な習慣があるからです。
たとえば、少なくともcn!という質問はTheta(n!)に尋ねることを意図したものです。 Cnを超えないステップ数!いくつかの定数c、C> 0のステップですが、代わりにO(n!)を使用することを選択しました。
別のインスタンス:Quicksort is O(n^2) in the worst case
、技術的には正しいが(最悪の場合でもヒープソートはO(n ^ 2)!)、実際に意味するのはQuicksort is Omega(n^2) in the worst case
です。
ウィキペディアで
総当たり検索による巡回セールスマン問題の解決。未成年者による展開で行列式を見つける。
http://en.wikipedia.org/wiki/Big_O_notation#Orders_of_common_functions
C#で
スペースの複雑さにおいてこれはO(N!)ではないでしょうか?なぜなら、C#の文字列は不変だからです。
string reverseString(string orgString) {
string reversedString = String.Empty;
for (int i = 0; i < orgString.Length; i++) {
reversedString += orgString[i];
}
return reversedString;
}
再帰呼び出しは正確にnを要するはずです。時間。これは、n個の異なる値の階乗時間をテストするようなコードです。内部ループはnで実行されます! jの異なる値の時間、したがって内部ループの複雑さはBig O(n!)
public static void NFactorialRuntime(int n)
{
Console.WriteLine(" N Fn N!");
for (int i = 1; i <= n; i++) // This loop is just to test n different values
{
int f = Fact(i);
for (int j = 1; j <= f; j++) // This is Factorial times
{ ++x; }
Console.WriteLine(" {0} {1} {2}", i, x, f);
x = 0;
}
}
N = 5のテスト結果は次のとおりです。正確に階乗時間を繰り返します。
N Fn N!
1 1 1
2 2 2
3 6 6
4 24 24
5 120 120
時間の複雑さnを持つ正確な関数!
// Big O(n!)
public static void NFactorialRuntime(int n)
{
for (int j = 1; j <= Fact(i); j++) { ++x; }
Console.WriteLine(" {0} {1} {2}", i, x, f);
}
おそらく行列の行列式を取得するために学習した再帰的方法(線形代数を取得した場合)はO(n!)時間かかります。私は特にそれをすべてコーディングする気はしませんが。
@clocksmithあなたは絶対に正しいです。これはn!を計算していません。 O(n!)でもありません。下の表のデータを収集して実行しました。列2と3を比較してください。 (#nFはnFacRuntimeFuncの呼び出し回数です)
0 0 1
1 1 1
2 4 2
3 15 6
4 65 24
5 325 120
6 1956 720
7 13699 5040
したがって、O(n!)よりもパフォーマンスがはるかに悪い場合は明らかです。以下は、nを計算するためのサンプルコードです。再帰的に。そのO(n)順序。
int Factorial(int n)
{
if (n == 1)
return 1;
else
return n * Factorial(n-1);
}
これは、パラメーターintと整数kの配列が与えられた複雑さO(n!)を持つ関数の簡単な例です。配列x + y = kから2つの項目がある場合、trueを返します。たとえば、tabが[1、2、3、4]およびk = 6の場合、2 + 4 = 6であるため、戻り値はtrueになります。
public boolean addToUpK(int[] tab, int k) {
boolean response = false;
for(int i=0; i<tab.length; i++) {
for(int j=i+1; j<tab.length; j++) {
if(tab[i]+tab[j]==k) {
return true;
}
}
}
return response;
}
ボーナスとして、これはjUnitを使用した単体テストであり、正常に動作します
@Test
public void testAddToUpK() {
DailyCodingProblem daProblem = new DailyCodingProblemImpl();
int tab[] = {10, 15, 3, 7};
int k = 17;
boolean result = true; //expected result because 10+7=17
assertTrue("expected value is true", daProblem.addToUpK(tab, k) == result);
k = 50;
result = false; //expected value because there's any two numbers from the list add up to 50
assertTrue("expected value is false", daProblem.addToUpK(tab, k) == result);
}
これの最も簡単な例は階乗関数です:
function factorial(n){
let fact=1;
for(var i=1; i<=n;i++){
fact=fact*i;
}
return fact;
}
O(n!)
Bogosort は、私が遭遇した唯一の「公式」なもので、O(n!)エリアへの冒険です。しかし、それは本質的にランダムであるため、保証されたO(n!)ではありません。