Takže ste tu. Uľavilo. Vyčerpané. Nakoniec ste prišli s riešením, ako vyriešiť zložitú otázku kódovania, ktorú sa vás pýtajúci žiada. Možno ste to dokonca napísali na tabuľu, riadok po riadku. A urobili ste si dobrý čas! Ste len 20 minút na stretnutie. Váš anketár musí byť ohromený.
Správny?
"Bude to fungovať, ale nejaké nápady, ako to urobiť efektívnejšie?"
Vaše srdce klesá. Mysleli ste si, že ste skončili so zložitou časťou návrhu algoritmu! Pokúsite sa vymyslieť viac spôsobov, ako problém vyriešiť, ale jediné, na čo si vzpomenete, je jediný prístup, s ktorým ste už prišli.
Stáva sa to takmer každému. A nie je to preto, že sú hlúpi. Je to preto, že väčšina ľudí nemá metódu na zlepšenie efektívnosti svojich algoritmov.
Pravda však je, že ich je veľa. Nabudúce, keď vás pne, skúste použiť tieto tri spoločné prístupy.
1. Použite Hashovu mapu
To je správne. Hašovacie mapy / asociatívne polia / slovníky (majú rôzne názvy v závislosti od toho, aký programovací jazyk používate) majú magickú schopnosť skrátiť dobu vykonávania algoritmov.
Predpokladajme napríklad, že najčastejšie sa opakujúce číslo nachádza v rade čísel.
Vaša prvá myšlienka by mohla byť skočiť do niektorých slučiek. Pre každé z našich čísel zistite jeho počet a zistite, či je to najväčšie. Ako získame počet pre každé číslo? Slučka cez pole, počítanie, koľkokrát sa to stane! Takže hovoríme o dvoch vnorených slučkách. V pseudokódu:
def get_mode (nums): max_count = 0 mode = null pre potenciálne_mode v nums: count = 0 pre číslo v our_array: count + = 1 if count> = max_count: mode = potential_mode max_count = count return mode
Práve teraz prechádzate cez celé pole raz pre každú položku v poli - ale môžeme urobiť lepšie. Vo veľkej notácii je to celkom O (n 2 ) čas.
Ak uložíme naše počty do hashovej mapy (mapovanie čísel na ich počty), môžeme problém vyriešiť iba jednou prechádzkou cez čas poľa (O (n)!):
def get_mode (nums): max_count = 0 mode = null countts = new HashMap, pričom každá hodnota sa začína na 0 pre potenciálny_mode v nums: count + = 1 ak sa počíta> max_count: mode = potenciálny_mode max_count = counts návratový režim
Oveľa rýchlejšie!
2. Použite bitovú manipuláciu
Toto vás skutočne odlíši od balenia. Nevzťahuje sa na každý problém, ale ak si ho ponecháte v zadnom vrecku a vyhodíte ho v správny čas, budete vyzerať ako rocková hviezda.
Tu je príklad: Predpokladajme, že sme mali rad čísel, kde sa každé číslo objavuje dvakrát, s výnimkou jedného čísla, ktoré sa vyskytuje iba raz. Píšeme funkciu, aby sme našli osamelé, neopakované číslo.
Prvým inštinktom môže byť použitie hashovej mapy, pretože sme o nej práve hovorili. To je dobrý inštinkt! A bude to fungovať pre tento. Môžeme si vytvoriť veľmi podobnú „počítaciu“ mapu a pomocou nej zistiť, ktoré číslo končí číslom 1.
Ale existuje ešte lepší spôsob. Ak ste oboznámení s bitovou manipuláciou, možno poznáte XOR. Jedinou vecou, ktorá je pre XOR špeciálna, je to, že ak XOR číslo sami so sebou, bity sa „zrušia“ na 0. Pre tento problém, ak budeme XOR každé číslo v poli spolu, zostane nám jedno číslo, ktoré neurobilo Zrušiť:
def find_unrepeating (nums): unpeateat = 0 for num in nums: unpeateat = unpeateat XOR num return nerepeat
3. Choďte zdola nahor
Napíš funkciu, ktorá vydá „n“ Fibonacciho číslo a dostane číslo n. Toto je klasika a veľmi dobre sa hodí na rekurziu:
def fib (n): ak n je 0 alebo 1: návrat 1 návratové vlákno (n-1) + vlákno (n-2)
Jednoduchá rekurzívna odpoveď však nie je jediná! Dôkladne premýšľajte o tom, čo táto funkcia robí. Predpokladajme, že n je 5. Na získanie odpovede rekurzívne volá vlákno (4) a vlákno (3). Čo to vlastne znamená pre vlákno (4)? Nazýva vlákno (3) a vlákno (2). Ale práve sme povedali, že sme už mali telefonát (3)! Táto roztomilá rekurzívna funkcia robí veľa opakovaných prác. Ukázalo sa, že celkové časové náklady sú O (2 n ). To je zlé - oveľa horšie ako O (n 2 ).
Namiesto návratu z n rekurzívne na 1, choďme „zdola nahor“ z 1 na n. Toto nám umožňuje preskočiť rekurziu:
def fib (n): previous = 0 previous_previous = 1 pre i v rozsahu 1 až n: current = previous + previous_previous previous_previous = previous previous = aktuálny návratný prúd
Kód je dlhší, ale je oveľa efektívnejší! Až do času O (n). Ako bonus s rozvinovaním rekurzívnych algoritmov šetríme miesto. Všetky tieto rekurzívne hovory sa hromadia v zásobníku hovorov, ktorý je uložený v pamäti a započítava sa do našich vesmírnych nákladov. Naša rekurzívna funkcia mala náklady na priestor O (n), ale táto iteračná funkcia zaberá priestor O (1).
Až nabudúce požiada váš anketár o zlepšenie efektívnosti vášho riešenia, skúste si prečítať tieto stratégie a zistiť, či vám pomôžu. Pri dostatočnom počte praxe sa pravdepodobne ocitnete priamo na optimalizovanom riešení a preskočíte naivnejšie riešenie. A to je skvelá vec. Neznamená to len, že sa stanete lepším anketárom - to znamená, že sa stanete lepším inžinierom.













