Maximálnà podpole
Na vstupu je pole ÄÃsel, napÅ. pole = [1, -2, 3, 4, -9, 6].
Ãkol znÃ: najdÄte souvislé podpole tohoto pole s maximálnÃm souÄtem prvků.
NapiÅ¡te funkci vraÅ¥MaxSouÄetPodpole(pole), která tento souÄet vrátÃ.
PÅÃklad:
vraÅ¥MaxSouÄetPodpole([-1, 2, 3, -9]) == 5 (souÄet zvýraznÄných prvků)
vraÅ¥MaxSouÄetPodpole([2, -1, 2, 3, -9]) == 6
vraÅ¥MaxSouÄetPodpole([-1, 2, 3, -9, 11]) == 11
vraÅ¥MaxSouÄetPodpole([-2, -1, 1, 2]) == 3
vraÅ¥MaxSouÄetPodpole([100, -9, 2, -3, 5]) == 100
vraÅ¥MaxSouÄetPodpole([1, 2, 3]) == 6 (vezmi vÅ¡e)
Jsou-li vÅ¡echny prvky záporné, znamená to, že nevezmeme žádný (podpole je prázdné), takže souÄet je nulový:
vraÅ¥MaxSouÄetPodpole([-1, -2, -3]) = 0
Snažte se prosÃme vymyslet rychlé ÅeÅ¡enÃ: O(n2) nebo dokonce O(n), jestliže to dokážete.
Pomalé ÅeÅ¡enÃ
Můžeme spoÄÃtat vÅ¡echny možné podsouÄty.
NejjednoduššÃm způsobem je vzÃt každý prvek a poÄÃtat souÄty vÅ¡ech podpolÃ, která jÃm zaÄÃnajÃ.
NapÅÃklad pro [-1, 2, 3, -9, 11]:
// ZaÄÃnajÃcà -1:
-1
-1 + 2
-1 + 2 + 3
-1 + 2 + 3 + (-9)
-1 + 2 + 3 + (-9) + 11
// ZaÄÃnajÃcà 2:
2
2 + 3
2 + 3 + (-9)
2 + 3 + (-9) + 11
// ZaÄÃnajÃcà 3:
3
3 + (-9)
3 + (-9) + 11
// ZaÄÃnajÃcà -9:
-9
-9 + 11
// ZaÄÃnajÃcà 11:
11
Kód je ve skuteÄnosti vnoÅený cyklus: vnÄjšà cyklus procházà prvky pole, vnitÅnà poÄÃtá podsouÄty poÄÃnaje aktuálnÃm prvkem.
function vraÅ¥MaxSouÄetPodpole(pole) {
let maxSouÄet = 0; // nevezmeme-li žádné prvky, vrátà se nula
for (let i = 0; i < pole.length; i++) {
let souÄetPevnýZaÄátek = 0;
for (let j = i; j < pole.length; j++) {
souÄetPevnýZaÄátek += pole[j];
maxSouÄet = Math.max(maxSouÄet, souÄetPevnýZaÄátek);
}
}
return maxSouÄet;
}
alert( vraÅ¥MaxSouÄetPodpole([-1, 2, 3, -9]) ); // 5
alert( vraÅ¥MaxSouÄetPodpole([-1, 2, 3, -9, 11]) ); // 11
alert( vraÅ¥MaxSouÄetPodpole([-2, -1, 1, 2]) ); // 3
alert( vraÅ¥MaxSouÄetPodpole([1, 2, 3]) ); // 6
alert( vraÅ¥MaxSouÄetPodpole([100, -9, 2, -3, 5]) ); // 100
Toto ÅeÅ¡enà má Äasovou složitost O(n2). Jinými slovy, když zvÄtÅ¡Ãme pole dvojnásobnÄ, algoritmus bude pracovat ÄtyÅikrát déle.
Pro velká pole (1000, 10000 nebo vÃce prvků) mohou takové algoritmy vést k vážnému zpomalenÃ.
Rychlé ÅeÅ¡enÃ
Budeme procházet prvky pole a pamatovat si aktuálnà ÄásteÄný souÄet prvků v promÄnné s. Bude-li s v nÄkterém bodÄ záporné, pÅiÅadÃme s=0. OdpovÄdà bude maximum vÅ¡ech takových s.
Pokud je popis pÅÃliÅ¡ vágnÃ, prosÃme nahlédnÄte do kódu, je dosti krátký:
function vraÅ¥MaxSouÄetPodpole(pole) {
let maxSouÄet = 0;
let ÄásteÄnýSouÄet = 0;
for (let prvek of pole) { // pro každý prvek pole
ÄásteÄnýSouÄet += prvek; // pÅiÄteme jej do ÄásteÄnýSouÄet
maxSouÄet = Math.max(maxSouÄet, ÄásteÄnýSouÄet); // zapamatujeme si maximum
if (ÄásteÄnýSouÄet < 0) ÄásteÄnýSouÄet = 0; // je-li souÄet záporný, vynulujeme ho
}
return maxSouÄet;
}
alert( vraÅ¥MaxSouÄetPodpole([-1, 2, 3, -9]) ); // 5
alert( vraÅ¥MaxSouÄetPodpole([-1, 2, 3, -9, 11]) ); // 11
alert( vraÅ¥MaxSouÄetPodpole([-2, -1, 1, 2]) ); // 3
alert( vraÅ¥MaxSouÄetPodpole([100, -9, 2, -3, 5]) ); // 100
alert( vraÅ¥MaxSouÄetPodpole([1, 2, 3]) ); // 6
alert( vraÅ¥MaxSouÄetPodpole([-1, -2, -3]) ); // 0
Tento algoritmus vyžaduje pÅesnÄ 1 průchod polem, takže jeho Äasová složitost je O(n).
PodrobnÄjšà informace o algoritmu můžete najÃt zde: Maximum subarray problem (Problém maximálnÃho podpole). NenÃ-li vám stále jasné, proÄ to funguje, potom si prosÃme projdÄte algoritmus na výše uvedených pÅÃkladech a podÃvejte se, jak funguje. Je to lepšà než jakákoli slova.