Questo sembra essere un problema per la programmazione dinamica. Quando si costruisce la matrice, si costruisce un altro array contenente la somma cumulativa fino a ciascun indice particolare. Quindi ogni i
in quell'array ha le somme da 1..i
.
Ora è facile vedere che la somma dei valori per gli indici p..q
è SUM(q) - SUM(p-1)
(con il caso particolare che SUM(0)
è 0
). Ovviamente sto usando indici basati su 1 qui ... Questa operazione è O (1), quindi ora hai solo bisogno di un algoritmo O (n) per trovare quello migliore.
Una soluzione semplice è tenere traccia di un p
e di q
e passarli attraverso l'array. Si espande con q
per iniziare. Quindi contragga p
ed espandi ripetutamente q
, come un bruco che striscia nell'array.
Per espandere q
:
p <- 1
q <- 1
while SUM(q) - SUM(p-1) < K
q <- q + 1
end while
Ora q
è nella posizione in cui la somma sottoarray ha appena superato (o è uguale a) K
. La lunghezza del sottoarray è q - p + 1
.
Dopo il ciclo q
si verifica se la lunghezza della sottostruttura è inferiore al valore corrente. Quindi fai avanzare di p
di un passo (in modo da evitare di saltare accidentalmente la soluzione ottimale) e riprovare.
Non hai davvero bisogno di creare l'array SUM
... Puoi semplicemente costruire la somma della sottomarca mentre vai ... Dovresti tornare a usare il 'vero' p
invece di quello appena prima .
subsum <- VAL(1)
p <- 1
q <- 1
while q <= N
-- Expand
while q < N and subsum < K
q <- q + 1
subsum <- subsum + VAL(q)
end while
-- Check the length against our current best
len <- q - p + 1
if len < bestlen
...
end if
-- Contract
subsum <- subsum - VAL(p)
p <- p + 1
end while
Note:
j_random_hacker detto: sarebbe utile per spiegare esattamente il motivo per cui è accettabile per esaminare solo la O (n) sottoarray distinte che questo algoritmo esamina, invece di tutti O (n^2) possibili sottoarray distinti
La filosofia di programmazione dinamica è:
- non seguire percorsi di soluzione che porteranno a un risultato non ottimale; e
- utilizzare la conoscenza delle soluzioni precedenti per calcolare una nuova soluzione.
In questo caso un'unica soluzione candidata (alcuni (p,q)
tale che p <= q
) viene calcolato sommando degli elementi. Poiché questi elementi sono numeri interi positivi, sappiamo che per qualsiasi soluzione candidata (p,q)
, la soluzione candidata (p,q+1)
sarà più grande.
E così sappiamo che se (p,q)
è una soluzione minima, allora non lo è (p,q+1)
. Terminiamo la ricerca non appena abbiamo un candidato, e testiamo se quel candidato è migliore di quello che abbiamo visto finora. Ciò significa che per ogni p
, abbiamo solo bisogno di testare un candidato. Ciò porta ad entrambi i valori p
e q
sempre crescenti, e quindi la ricerca è lineare.
L'altra parte di questo (utilizzando soluzioni precedenti) deriva dal riconoscimento di sum(p,q+1) = sum(p,q) + X(q+1)
e allo stesso modo sum(p+1,q) = sum(p,q) - X(p)
. Pertanto, non è necessario sommare tutti gli elementi tra p
e q
ad ogni passaggio. Dobbiamo solo aggiungere o sottrarre un valore ogni volta che avanza uno dei puntatori di ricerca.
Spero che questo aiuti.
L'ordinamento degli elementi non verrà risolto? Cosa intendi per sottotitolo? Una sequenza contigua di elementi nell'array o un sottoinsieme degli elementi nell'array? – nhahtdh
L'ordinamento non può essere applicato in questo caso poiché cambierà l'ordine dell'articolo. – Thinhbk
Sto assumendo che l'ordine non è importante. cioè {1,2,3} e {2,1,3} sono trattati come stessi sotto-array. Subrarray si riferisce a un sottoinsieme di elementi e NON necessariamente a una sequenza contigua in questo contesto. –