To wydaje się być problemem dla programowania dynamicznego. Podczas budowania macierzy budujemy kolejną tablicę zawierającą sumę skumulowaną do każdego konkretnego indeksu. Więc każdy i
w tej tablicy ma sumy od 1..i
.
Teraz to łatwo zauważyć, że suma wartości dla indeksów p..q
jest SUM(q) - SUM(p-1)
(ze szczególnym przypadku, SUM(0)
jest 0
). Oczywiście używam tutaj indeksów 1-bazowych ... Ta operacja to O (1), więc teraz potrzebujesz tylko algorytmu O (n), aby znaleźć najlepszy.
Prostym rozwiązaniem jest śledzenie p
i q
i przechodzenie przez tablicę. Na początek rozwijasz się pod numerem q
. Następnie zamawiasz p
i wielokrotnie rozwiń q
, jak gąsienica przeszukiwana przez twoją tablicę.
Aby rozwinąć q
:
p <- 1
q <- 1
while SUM(q) - SUM(p-1) < K
q <- q + 1
end while
Teraz q
jest w pozycji, w której suma subarray właśnie przekroczony (lub równy) K
. Długość podprzestrzeni to q - p + 1
.
Po pętli q
sprawdza się, czy długość podprzestrzeni jest mniejsza od aktualnej. Następnie należy wykonać krok o krok p
(tak, aby nie przypadkowo pominąć optymalnego rozwiązania) i przejść ponownie.
Nie musisz tworzyć macierzy SUM
... Możesz po prostu zbudować sumę podprzestrzeni w trakcie pracy ... Musisz wrócić do korzystania z "prawdziwej" p
zamiast tej, która była tuż przed .
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
Uwagi:
j_random_hacker powiedział: to pomóc wyjaśnić, dlaczego dopuszczalne jest zbadanie tylko O (N) różne subarrays że ten algorytm przeprowadza oględziny, zamiast wszystkich O (n^2) różnych możliwych subarrays
dynamiczny filozofii programowania:
- nie podążaj za ścieżkami rozwiązania, które doprowadzą do nieoptymalnego wyniku; i
- wykorzystać wiedzę z wcześniejszych rozwiązań do obliczenia nowego rozwiązania.
W tym przypadku jednego kandydata roztworu (około (p,q)
tak, że p <= q
) oblicza się poprzez sumowanie elementów. Ponieważ te elementy są liczbami całkowitymi dodatnimi, wiemy, że dla dowolnego kandydata na rozwiązanie (p,q)
, kandydat na rozwiązanie (p,q+1)
będzie większy.
A więc wiemy, że jeśli (p,q)
jest rozwiązaniem minimalnym, to nie jest to (p,q+1)
. Kończymy nasze poszukiwania, gdy tylko mamy kandydata, i sprawdzamy, czy ten kandydat jest lepszy niż jakikolwiek, który widzieliśmy do tej pory. Oznacza to, że dla każdego p
musimy przetestować tylko jednego kandydata. To prowadzi do tego, że zarówno p
, jak i q
ciągle się zwiększa, a zatem wyszukiwanie jest liniowe.
Inna część tego (korzystanie z wcześniejszych rozwiązań) pochodzi od rozpoznania, że sum(p,q+1) = sum(p,q) + X(q+1)
i podobnie sum(p+1,q) = sum(p,q) - X(p)
. Dlatego nie musimy sumować wszystkich elementów między p
i q
na każdym kroku. Musimy tylko dodać lub odjąć jedną wartość za każdym razem, gdy przesuwamy jeden ze wskaźników wyszukiwania.
Nadzieję, że pomaga.
Nie posortujesz bałaganu w kolejności elementów? Co masz na myśli przez subarray? Ciągła sekwencja elementów w tablicy lub podzbiór elementów w tablicy? – nhahtdh
Sortowanie nie może być zastosowane w tym przypadku, ponieważ zmieni kolejność pozycji. – Thinhbk
Przyjmuję, że zamówienie nie jest ważne. tj. {1,2,3} i {2,1,3} są traktowane jako te same podrzędne. Subrarray odwołuje się do podzbioru elementów i niekoniecznie ciągłej sekwencji w tym kontekście. –