web-dev-qa-db-de.com

Beispiel für Big O von 2 ^ n

Ich kann mir also vorstellen, was ein Algorithmus ist, der eine Komplexität von n ^ c hat, nur die Anzahl der verschachtelten for-Schleifen. 

for (var i = 0; i < dataset.len; i++ {
    for (var j = 0; j < dataset.len; j++) {
        //do stuff with i and j
    }
}

Log ist etwas, das den Datensatz jedes Mal in zwei Hälften aufspaltet. Die binäre Suche macht dies (ist nicht ganz sicher, wie der Code dafür aussieht). 

Aber was ist ein einfaches Beispiel für einen Algorithmus, der c ^ n oder genauer 2 ^ n ist. Basiert O (2 ^ n) auf Datenschleifen? Oder wie werden Daten aufgeteilt? Oder etwas ganz anderes?

20
dlkulp

Algorithmen mit Laufzeit O (2 ^ N) sind oft rekursive Algorithmen, die ein Problem der Größe N lösen, indem sie zwei kleinere Probleme der Größe N-1 rekursiv lösen.

Dieses Programm druckt zum Beispiel alle erforderlichen Schritte aus, um das berühmte Problem "Towers of Hanoi" für N-Festplatten im Pseudocode zu lösen

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);
    }
}

Sei T(N) die Zeit, die N Platten benötigen.

Wir haben:

T(1) = O(1)
and
T(N) = O(1) + 2*T(N-1) when N>1

Wenn Sie den letzten Begriff wiederholt erweitern, erhalten Sie:

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)

Um dies wirklich herauszufinden, müssen Sie nur wissen, dass bestimmte Muster in der Wiederholungsbeziehung zu exponentiellen Ergebnissen führen. Im Allgemeinen bedeutet T(N) = ... + C*T(N-1) mit C > 1 O (x ^ N). Sehen:

https://en.wikipedia.org/wiki/Recurrence_relation

21
Matt Timmermans

Denken Sie über z. Iteration über alle möglichen Teilmengen einer Menge. Diese Art von Algorithmen wird beispielsweise für ein allgemeines Rucksackproblem verwendet. 

Wenn Sie nicht verstehen können, wie die Iteration über Subsets in O (2 ^ n) übersetzt wird, stellen Sie sich eine Menge von n Switches vor, die jeweils einem Element einer Menge entsprechen. Jetzt kann jeder der Schalter ein- oder ausgeschaltet werden. Stellen Sie sich "ein" als Teil der Untermenge vor. Beachten Sie, wie viele Kombinationen möglich sind: 2 ^ n.

Wenn Sie ein Beispiel im Code sehen möchten, ist es in der Regel einfacher, hier über Rekursion nachzudenken, aber ich kann mir nicht od ein anderes schönes und verständliches Beispiel vorstellen. 

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

  return Fibonacci(number - 2) + Fibonacci(number - 1);
 }

Das Wachstum verdoppelt sich mit jeder Addition zum Eingabedatensatz. Die Wachstumskurve einer O(2N) Funktion ist exponentiell - sie beginnt sehr flach und steigt dann meteorisch an .. Mein Beispiel für großes O (2 ^ n), aber viel besser ist dies:

public void solve(int n, String start, String auxiliary, String end) {
   if (n == 1) {
       System.out.println(start + " -> " + end);
   } else {
       solve(n - 1, start, end, auxiliary);
       System.out.println(start + " -> " + end);
       solve(n - 1, auxiliary, start, end);
   }

Bei dieser Methode druckt das Programm alle Schritte, um das "Tower of Hanoi" -Problem zu lösen. Beide Beispiele verwenden rekursive Problemlösungen und hatten große O (2 ^ n) -Laufzeit.

1
darthir21

c ^ N = Alle Kombinationen von n Elementen eines c großen Alphabets.

Genauer gesagt ist 2 ^ N alle Zahlen, die mit N Bits darstellbar sind.

Die häufigsten Fälle werden rekursiv implementiert, etwa:

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);
}
0
Sorin

Hier ist ein Codeclip, der die Wertesumme jeder Kombination von Werten in einem Warenarray berechnet (und value ist eine globale Arrayvariable):

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)
}

Wie Sie sehen, ist es rekursiv. Wir können Schleifen einfügen, um Polynomial Komplexität zu erhalten, und rekursiv verwenden, um Exponential Komplexität zu erhalten.

0
boileryao

Hier sind zwei einfache Beispiele für Python mit Big O/Landau (2 ^ N):

#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')
0
grepit