Try   HackMD

ADS úlohy E - podobne

Nejprve je potřeba si rozmyslet, zda přidání dalšího prvku na konec posloupnosti ovlivní dosavadní posloupnosti:

Budu-li postupovat v posloupnosti od konce do začátku, mohu najít první číslo, jehož rozdíl s posledním číslem přesáhne toleranci (

k). Pro další výpočty pak mi stačí uvažovat pouze úsek napravo od tohoto čísla. Zároveň je však potřeba si uvědomit, že i předposlední číslo již vyhradilo jakýsi úsek, ve kterém má smysl zkoumat podposloupnosti - budu se tak zabývat kratším z těchto úseků.

Nyní vezmu následující situaci: mám posloupnost

P s finálním prvkem
Pn+1
, pro nějž je zarážka na pozici
s1
.

Jelikož se jedná o první zarážku, celá posloupnost od

0 do
n
je platná a tuto posloupnost nelze rozšířit zleva ani zprava. Označím tak
t0=n
a
s0=0
, což znamená, že podposloupnost má délku
t0s0
.

Dále, mezi

Ps+1 a
Pn+1
nevznikla žádná zarážka, a tak mohu postup opakovat (jako bych opět počítal od nuly), dokud nevznikne další zarážka.

Algoritmus (1):

Vstup: posloupnost

P s prvky od
0
do
n
, hranice
k
.

  1. s0=0
  2. x=0
  3. Pro
    u{1n}
    :
    1. Pro
      v{u1sx}:
    2. Je-li
      |PuPv|>k
      :
      1. tx=u
      2. x=x+1
      3. sx=v+1
      4. Ukonči cyklus
  4. tx=n
  5. Najdi takové
    sx
    , aby rozdíl
    txsx
    byl co největší.
  6. Výstup: Nejdelší posloupnost prvků
    PsxPtx1
    .

Zdůvodnění:

Algoritmus vlastně rozkouskuje interval na souvislé podposloupnosti, které již nejdou rozšířit. (nemusí být nutně disjunktní). Vybrat tu nejdelší nepředstavuje žádný problém.
Levá zarážka

sx (inkluzivní) vzniká tehdy, kdy zkoumané číslo
Pu
nelze odečíst od čísla před touto zarážkou - proto nelze posloupnost, ve které se nachází
Pu
, rozšířit směrem doleva. Ze stejného důvodu se
Pu
stává pravou zarážkou (již nepatřící do ní) -
tx
pro předchozí podposloupnost.

Složitost(1):

Pokud chci pouze nejdelší podposloupnost, pak mi stačí uchovávat si v paměti maximum a momentální podposloupnost, takže paměťové nároky budou konstantní. V opačném případě budu potřebovat lineární paměť na všechny zarážky.
Časová složitost závisí na tom, kolik budu mít zarážek. Nemám-li žádné, pak celá posloupnost je "v toleranci" a složitost tak bude kvadratická.

Optimalizace:

Nevznikne-li pro daný prvek

Pu zarážka, pak pro následující prvky budu porovnávat rozdíl přes naprosto stejné prvky. Toto bych si mohl ušetřit tím, že pro daný interval zjistím maximum a minimum a budu porovnávat jen rozdíl mezi maximem a minimem.

Algoritmus(2):

Vstup: posloupnost

P s prvky od
0
do
n
, hranice
k
.

  1. s0=0
  2. x=0
  3. maxim=,minim=+
  4. d=0
  5. z=true
  6. Pro
    u{1n}
    :
    1. Je-li
      z=false
      a je-li
      |Pumaxim|k
      a
      |Puminim|k
      :
      2.
      maxim=Max(Pu,maxim)

      3.
      minim=Min(Pu,minim)

      4. Pokračuj dále
    2. Jinak (je potřeba vytvořit zarážku):
    3. z=false
    4. Pro
      v{u1sx}:
    5. Je-li
      |PuPv|>k
      :
      1. z=true
      2. tx=u
      3. x=x+1
      4. sx=v+1
      5. maxim=Max(PsxPu)
      6. minim=Min(PsxPu
      7. Ukonči cyklus
  7. tx=n
  8. Najdi takové
    sx
    , aby rozdíl
    txsx
    byl co největší.
  9. Výstup: Nejdelší posloupnost prvků
    PsxPtx1
    .

Složitost (2):

Paměťová složitost výše popsaného je

O(n), pokud již zaznamenávám maximum, pak
O(1)
.

Co se týče časové složitosti: Pouhé rozšíření posloupnosti (nový prvek se vleze do tolerance maxima i minima) má složitost O(1). V případě, že je potřeba posloupnost uzavřít, může být opět potřeba prohledat

O(n) prvků, levá zarážka se posune o jeden prvek, a tak složitost v nejhorším případě by stále byla
O(n2)
.