Algorithm 2^n的大O示例

Algorithm 2^n的大O示例,algorithm,big-o,time-complexity,Algorithm,Big O,Time Complexity,所以我可以想象什么是复杂度为n^c的算法,只是嵌套for循环的数量 for (var i = 0; i < dataset.len; i++ { for (var j = 0; j < dataset.len; j++) { //do stuff with i and j } } for(var i=0;i

所以我可以想象什么是复杂度为n^c的算法,只是嵌套for循环的数量

for (var i = 0; i < dataset.len; i++ {
    for (var j = 0; j < dataset.len; j++) {
        //do stuff with i and j
    }
}
for(var i=0;i
日志每次都会将数据集一分为二,二进制搜索就是这样做的(不完全确定这是什么代码)


但是什么是c^n或更具体地说是2^n的算法的一个简单例子呢?O(2^n)是基于数据循环的?或者数据是如何分割的?或者是完全其他的东西?

想想,例如,迭代集合中所有可能的子集。这种算法被用于一个广义背包问题

如果您发现很难理解在子集上迭代如何转换为O(2^n),请想象一组n个开关,每个开关对应于集合中的一个元素。现在,每个开关都可以打开或关闭。将“打开”视为在子集中。注意,有多少个组合是可能的:2^n

如果你想在代码中看到一个例子,在这里考虑递归通常比较容易,但我现在想不出任何其他好的、可以理解的例子

  int Fibonacci(int number)
 {
  if (number <= 1) return number;

  return Fibonacci(number - 2) + Fibonacci(number - 1);
 }
在这个方法中,程序打印所有的动作来解决“河内塔”问题。
这两个示例都使用递归来解决问题,并且运行时间都很大。

运行时间为O(2^n)的算法通常是递归算法,通过递归解决两个大小为n-1的较小问题来解决大小为n的问题

例如,这个程序用伪代码为N个磁盘打印出解决著名的“河内塔”问题所需的所有动作

void solve_hanoi(int N, string from_peg, string to_peg, string spare_peg)
{
    if (N<1) {
        return;
    }
    if (N>1) {
        solve_hanoi(N-1, from_peg, spare_peg, to_peg);
    }
    print "move from " + from_peg + " to " + to_peg;
    if (N>1) {
        solve_hanoi(N-1, spare_peg, to_peg, from_peg);
    }
}
如果重复展开上一个术语,则会得到:

T(N) = 3*O(1) + 4*T(N-2)
T(N) = 7*O(1) + 8*T(N-3)
...
T(N) = (2^(N-1)-1)*O(1) + (2^(N-1))*T(1)
T(N) = (2^N - 1)*O(1)
T(N) = O(2^N)
要真正弄清楚这一点,您只需知道递归关系中的某些模式会导致指数结果。通常
T(N)=…+C*T(N-1)
with
C>1
表示O(x^N)。请参阅:


c^N=大小为
c
的字母表中
N
元素的所有组合

更具体地说,2^N是可以用N位表示的所有数字

常见情况是递归实现的,类似于:

vector<int> bits;
int N
void find_solution(int pos) {
   if (pos == N) {
     check_solution();
     return;
   }
   bits[pos] = 0;
   find_solution(pos + 1);
   bits[pos] = 1;
   find_solution(pos + 1);
}
矢量位;
int N
无效查找解决方案(int pos){
如果(pos==N){
检查_溶液();
返回;
}
位[pos]=0;
找到解决方案(位置+1);
位[pos]=1;
找到解决方案(位置+1);
}

这是一个代码片段,用于计算商品数组中每个值组合的值和(并且
value
是一个全局数组变量):

fun-boom(idx:Int、pre:Int、include:Boolean){
如果(idx<0)返回
动臂(idx-1,前+如果(包括)值[idx]否则为0,为真)
动臂(idx-1,前+如果(包括)值[idx]否则为0,假)
println(pre+if(include)值[idx]else 0)
}

正如您所看到的,它是递归的。我们可以插入循环以获得
多项式
复杂度,并使用递归来获得
指数
复杂度。

这里有两个python中使用大O/Landau(2^N)的简单示例:


假设你想猜智能手机的PIN码,这个PIN码是一个4位整数。你知道一个4位数字的最大位数是14位,2^14是16384。所以,你必须猜这个PIN码的值,比如说,14位的正确组合

<> P>唯一的方法是蛮力。因此,为了简单起见,考虑这个简单的2位字,你想猜对,每个位有2个可能的值,0或1。所以,所有的可能性都是:

00
01
10
11
我们从逻辑电路设计中知道,一个n位字的所有可能组合都是2^n个可能的组合。因此,正如我们前面看到的,2^2是4个可能的组合

这同样适用于14位整数管脚,因此猜测管脚将需要您解决一个2^14可能的结果难题,因此是一个时间复杂度为O(2^n)的算法

所以,那些类型的问题,在一个集合中元素的组合不同,你必须通过尝试所有可能的组合来解决这个问题,将有这个O(2^n)时间复杂度。但是,求幂基数不必是2。在上面的示例中,它是以2为基数的,因为每个元素、每个位都有两个可能的值,这在其他问题中是不可能的

O(2^n)算法的另一个很好的例子是递归背包。你必须尝试不同的组合来最大化值,集合中的每个元素都有两个可能的值,不管我们是否接受它


问题是O(3^n)时间复杂度,因为n个字符串、删除、插入或替换中的每一个都有3个决定可供选择。

您应该解释为什么它具有指数复杂度-这并不明显。此外,这是一个坏例子,因为您可以轻松地“修复”这个算法有线性复杂度——就好像你想故意浪费处理能力一样。更好的例子会显示一个算法,它可以计算一些很难/不可能快速完成的事情。计算第n个Fibonacci数的简单递归函数是另一个典型的例子。我仍然不会去看那些代码,而是做一个我们无法推导出2^n,但这确实非常有帮助。我添加了一个可能help@EsotericScreenNameO(2^n)不是简单计算第n个斐波那契数的时间复杂度的严格界限,它是O(φ^n)其中phi是黄金比例。所以我认为这不是一个很好的答案,它隐含地要求算法是θ(2^n)。O(2^n)通常可以变成O(n)与dp这实际上是
O(n*2^n)
复杂性。@SanketMakani迭代所有位长
n
的二进制数与
O(n*2^n)有什么关联
?当然,除非你假定一个n位数字的增量为
O(n)
(这是完全正确的,但许多人不同意),这有点类似于说,迭代
n
数字需要
O(n log n)vector<int> bits;
int N
void find_solution(int pos) {
   if (pos == N) {
     check_solution();
     return;
   }
   bits[pos] = 0;
   find_solution(pos + 1);
   bits[pos] = 1;
   find_solution(pos + 1);
}
fun boom(idx: Int, pre: Int, include: Boolean) {
    if (idx < 0) return
    boom(idx - 1, pre + if (include) values[idx] else 0, true)
    boom(idx - 1, pre + if (include) values[idx] else 0, false)
    println(pre + if (include) values[idx] else 0)
}
#fibonacci 
def fib(num):    
    if num==0 or num==1:
        return num
    else:
        return fib(num-1)+fib(num-2)

num=10
for i in range(0,num):
    print(fib(i))


#tower of Hanoi
def move(disk , from, to, aux):
    if disk >= 1:
        # from twoer , auxilart 
        move(disk-1, from, aux, to)
        print ("Move disk", disk, "from rod", from_rod, "to rod", to_rod)
        move(disk-1, aux, to, from)

n = 3
move(n, 'A', 'B', 'C')
00
01
10
11