Çakışan alt problemler - Overlapping subproblems

İçinde bilgisayar Bilimi, bir sorun sahip olduğu söyleniyor örtüşen alt problemler Sorun, birkaç kez yeniden kullanılan alt problemlere bölünebilirse veya problem için özyinelemeli bir algoritma, her zaman yeni alt problemler oluşturmak yerine aynı alt problemi defalarca çözerse.[1][2][3]

Örneğin, hesaplama sorunu Fibonacci Dizisi örtüşen alt problemler sergiler. Hesaplama sorunu ninci Fibonacci numarası F(n), bilgi işlemin alt problemlerine ayrılabilir F(n - 1) ve F(n - 2) ve ardından ikisini ekliyoruz. Bilgi işlemin alt problemi F(n - 1) kendisi bilgi işlem içeren bir alt probleme bölünebilirF(n - 2). Bu nedenle, hesaplama F(n - 2) yeniden kullanılır ve Fibonacci dizisi böylece örtüşen alt problemler sergiler.

Saf yinelemeli böyle bir soruna yaklaşım genellikle bir üstel karmaşıklık. Sorun aynı zamanda bir optimal altyapı Emlak, dinamik program bunu halletmenin iyi bir yoludur.

C'de Fibonacci dizisi örneği

Aşağıdakileri göz önünde bulundur C kod:

#Dahil etmek <stdio.h>#define N 5statik int fibMem[N];int fibonacci(int n) {	int r = 1;	Eğer (n > 2) {		r = fibonacci(n - 1) + fibonacci(n - 2);	}	fibMem[n - 1] = r;	dönüş r;}geçersiz baskıFibonacci() {    int ben;    için (ben = 1; ben <= N; ben++) {        printf("fibonacci (% d):% d n", ben, fibMem[ben - 1]);    }}int ana(geçersiz) {    fibonacci(N);	baskıFibonacci();	dönüş 0;}/* Çıktı:    fibonacci (1): 1    fibonacci (2): 1    fibonacci (3): 2    fibonacci (4): 3    fibonacci (5): 5 * /

Yürütüldüğünde, fibonacci işlevi, dizideki bazı sayıların değerini, bu diyagramla görselleştirilebilen bir modeli izleyerek birçok kez hesaplar:

f (5) = f (4) + f (3) = 5 | | | f (3) = f (2) + f (1) = 2 | | | | | f (1) = 1 | | | f (2) = 1 | f (4) = f (3) + f (2) = 3 | | | f (2) = 1 | f (3) = f (2) + f (1) = 2 | | | f (1) = 1 | f (2) = 1

Bununla birlikte, avantajlarından yararlanabiliriz hafızaya alma ve değiştir fibonacci faydalanma işlevi fibMem böyle:

int fibonacci(int n) {	int r = 1;	Eğer (fibMem[n - 1] != 0) {		r = fibMem[n - 1];	} Başka {		Eğer (n > 2) {			r = fibonacci(n - 1) + fibonacci(n - 2);		}		fibMem[n - 1] = r;	}	dönüş r;}

Bu çok daha etkilidir çünkü değer r zaten belirli bir süre için hesaplandı n ve içinde saklandı fibMem [n - 1]işlev, daha fazla özyinelemeli işlev çağrıları yapmak yerine yalnızca depolanan değeri döndürebilir. Bu, bu diyagramla görselleştirilebilen bir modelle sonuçlanır:

f (5) = f (4) + f (3) = 5 | | f (4) = f (3) + f (2) = 3 | | f (3) = f (2) + f (1) = 2 | | | f (1) = 1 | f (2) = 1

Aradaki fark çok önemli görünmeyebilir. N 5, ancak değeri arttıkça, orijinalin karmaşıklığı fibonacci fonksiyon katlanarak artar, revize edilmiş versiyon ise daha doğrusal olarak artar.

Ayrıca bakınız

Referanslar

  1. ^ Algoritmalara Giriş, 2. baskı, (Cormen, Leiserson, Rivest ve Stein) 2001, s. 327. ISBN  0-262-03293-7.
  2. ^ Algoritmalara Giriş, 3. baskı, (Cormen, Leiserson, Rivest ve Stein) 2014, s. 384. ISBN  9780262033848.
  3. ^ Dinamik Programlama: Örtüşen Alt Problemler, Optimal Alt Yapı, MIT Video.