Se sei qui, è probabile che tu stia cercando di risolvere il “Problema del subarray massimo” e ti sia imbattuto nell’algoritmo di Kadane ma non sei riuscito a capire come funziona qualcosa del genere. O forse eri stanco di usare l’algoritmo di Kadane come una “scatola nera”. O forse volevi capire l’aspetto della programmazione dinamica di esso. O forse vuoi solo conoscere un nuovo concetto che può renderti migliore nella programmazione. Qualunque sia la ragione, sei arrivato nel posto giusto.,

Per comprendere meglio l’algoritmo di Kadane, in primo luogo, vorremmo passare attraverso una breve introduzione della programmazione dinamica. Quindi, esamineremo un problema di programmazione abbastanza popolare, il problema massimo dei sottoarray. Vedremo come questo problema può essere risolto usando un approccio a forza bruta e poi cercheremo di migliorare il nostro approccio e trovare un algoritmo migliore, aka, l’algoritmo di Kadane.

Quindi, entriamo in esso.,

Programmazione dinamica

La programmazione dinamica è un metodo per risolvere un problema complesso scomponendolo in una raccolta di sottoproblemi più semplici, risolvendo ciascuno di questi sottoproblemi solo una volta e memorizzando le loro soluzioni utilizzando una struttura dati basata sulla memoria (array, map, ecc.). Quindi la prossima volta che si verifica lo stesso sotto-problema, invece di ricalcolare la sua soluzione, si cerca semplicemente la soluzione precedentemente calcolata, risparmiando così tempo di calcolo.

Chi non riesce a ricordare il passato è condannato a ripeterlo., – Programmazione dinamica

Ecco una brillante spiegazione sul concetto di programmazione dinamica su Quora-La risposta di Jonathan Paulson a Come dovrei spiegare la programmazione dinamica a un bambino di 4 anni?

Anche se c’è di più nella programmazione dinamica, andremo avanti per capire il problema del sottoarray massimo.

Problema massimo di sottoarray

Il problema massimo di sottoarray è il compito di trovare la somma più grande possibile di un sottoarray contiguo, all’interno di un dato array unidimensionale A di numeri.,

Somma Massima Sottomatrice (In Giallo)

Per esempio, per la matrice di cui sopra, il contiguo sottomatrice con la più grande somma , con la somma di 6. Useremmo questo array come esempio per il resto di questo articolo. Inoltre, assumeremmo che questo array sia indicizzato a zero, cioè -2 sarebbe chiamato come l’elemento ” 0th ” dell’array e così via. Inoltre, A rappresenterebbe il valore all’indice i.,

Ora, daremo un’occhiata a una soluzione molto ovvia al problema dato.

Approccio alla forza bruta

Una soluzione molto ovvia ma non così buona è calcolare la somma di ogni possibile sottoarray e il massimo di quelli sarebbe la soluzione. Possiamo iniziare dall’indice 0 e calcolare la somma di ogni possibile sottoarray a partire dall’elemento A, come mostrato nella figura seguente. Quindi, calcoleremo la somma di ogni possibile sottoarray a partire da A, A e così via fino ad A, dove n denota la dimensione dell’array (n = 9 nel nostro caso)., Si noti che ogni singolo elemento è un sottoarray stesso.

metodo della Forza Bruta: Iterazione 0 (a sinistra) e l’Iterazione 1 (a destra)

chiameremo l’importo massimo di subarray di partenza con Un elemento il local_maximum all’indice. Così, dopo aver attraversato tutti gli indici, si sarebbe lasciato con local_maximum per tutti gli indici. Infine, possiamo trovare il massimo di questi local_maximums e otterremmo la soluzione finale, cioè, la somma massima possibile. Chiameremmo questo global_maximum.

Ma potresti notare che questo non è un metodo molto buono perché all’aumentare della dimensione dell’array, il numero di possibili sottoarray aumenta rapidamente, aumentando così la complessità computazionale. O per essere più precisi, se la dimensione dell’array è n, allora la complessità temporale di questa soluzione è O(n2) che non è molto buona.

Come possiamo migliorare questo? C’è un modo per usare il concetto di programmazione dinamica? Scopriamolo.,

L’algoritmo di Kadane

In questa sezione, useremmo di nuovo l’approccio alla forza bruta discusso sopra, ma questa volta inizieremmo all’indietro. Come sarebbe d’aiuto? Vediamo.

Inizieremmo dall’ultimo elemento e calcoleremmo la somma di ogni possibile sottoarray che termina con l’elemento A, come mostrato nella figura seguente. Quindi, calcoleremmo la somma di ogni possibile sottoarray che termina con A, A e così via fino ad A.,

Indietro metodo della Forza Bruta: Iterazione 0 (a sinistra) e l’Iterazione 1 (a destra)

Ora concentriamoci sul subarray termina con l’elemento A (=-1) e (=2) come mostrato nella figura sottostante.,

Dalla figura di cui sopra, vediamo che il local_maximum è uguale a 3, che è la somma della sottomatrice . Ora dai un’occhiata ai subarray che terminano con A. Noterai che questi subarray possono essere divisi in due parti, i subarray che terminano con A (evidenziati con il giallo) e il singolo elemento subarray A (in verde).

Diciamo che in qualche modo conosco il local_maximum., Quindi vediamo che per calcolare il local_maximum, non abbiamo bisogno di calcolare la somma di tutti i subarray che terminano con A poiché conosciamo già il risultato degli array che terminano con A. Nota che se l’array ha la somma massima, allora abbiamo solo bisogno di controllare gli array evidenziati con le frecce rosse per calcolare local_maximum. E questo ci porta al principio su cui funziona l’algoritmo di Kadane.

local_maximum all’indice i è il massimo di A e la somma di A e local_maximum all’indice i-1.,

Utilizzando il metodo di cui sopra, abbiamo bisogno di scorrere la matrice solo una volta, che è molto meglio rispetto al nostro precedente metodo della forza bruta. O per essere più precisi, la complessità temporale dell’algoritmo di Kadane è O(n).

Infine, vediamo come tutto questo funzionerebbe nel codice.,

Codice Walkthrough

Di seguito è riportata un’implementazione molto autoesplicativa (in C++) di una funzione che prende un array come argomento e restituisce la somma del sottoarray massimo.

Nota che invece di utilizzare un array per memorizzare local_maximums, siamo semplicemente memorizzare l’ultima local_maximum in una variabile di tipo int ‘local_max’ perché è di questo che abbiamo bisogno di calcolare prossimo local_maximum., Inoltre, come stiamo usando una variabile ‘global_max’ per tenere traccia del valore massimo di local_maximum, che alla fine risulta essere l’output richiesto.

Conclusione

a Causa del modo in cui questo viene utilizzato un algoritmo ottimale sottostrutture (il massimo sottomatrice che terminano in ogni posizione viene calcolata in modo semplice, legate da una, ma più piccola e la sovrapposizione subproblem: il massimo sottomatrice che termina alla posizione precedente) questo algoritmo può essere visto come un semplice esempio di programmazione dinamica., L’algoritmo di Kadane è in grado di trovare la somma massima di un sottoarray contiguo in un array con un runtime di O(n).

Articles

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *