什么是一个 O(n!)
函数的代码示例?它应该在参考 n
的情况下以适当数量的操作运行;也就是说,我正在询问时间复杂度。
什么是一个 O(n!)
函数的代码示例?它应该在参考 n
的情况下以适当数量的操作运行;也就是说,我正在询问时间复杂度。
这就是一个非常简单的例子,演示了一个运行时间为O(n!)
(其中n
是函数参数)的函数:
void nFacRuntimeFunc(int n) {
for(int i=0; i<n; i++) {
nFacRuntimeFunc(n-1);
}
}
O(n!)
(更重要的是Θ(n!)
)。是的,循环中调用的函数的时间复杂度会影响循环的时间复杂度。如果循环执行了n
次,并且循环中的函数执行了(n-1)!
步骤,那么总共将执行n * (n-1)! = n!
个步骤。这正是你证明该函数的时间复杂度为Θ(n!)
的方法。 - sepp2k一个经典的例子是通过暴力搜索解决旅行商问题 (traveling salesman problem)。
如果有 N
个城市,暴力搜索方法会尝试每一种这些 N
个城市的排列组合,以找到最便宜的那一个。现在,具有 N
个城市的排列组合数为 N!
,使得其复杂度是阶乘级别的 (O(N!)
)。
任何计算给定数组所有排列组合的算法都是O(N!)
的。
template <class Iter>
void snail_sort(Iter first, Iter last)
{
while (next_permutation(first, last)) {}
}
next_permutation
需要线性时间,因此朴素计算会给出O(n*n!)的时间(严格大于O(n!))。你必须证明next_permutation
在平均情况下需要O(1)时间才能使其起作用。 - Paul Hankinnext_permutation
返回字典序中的下一个排列并返回 true,或者返回最小的排列(即排序后的排列)并返回 false 如果不存在下一个排列。 - Bernhard Barker通过余子式展开法求行列式。
这里有非常好的解释(链接)。
# 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;
}
最简单的例子 :)
伪代码:
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!)
这里有一个真实的例子——如何生成一组项目的所有排列?
在维基百科中
通过暴力搜索解决旅行商问题;通过行列式的余子式展开来找到行列式的值。
http://en.wikipedia.org/wiki/Big_O_notation#Orders_of_common_functions
string reverseString(string orgString) {
string reversedString = String.Empty;
for (int i = 0; i < orgString.Length; i++) {
reversedString += orgString[i];
}
return reversedString;
}