Tietorakenteet, laskuharjoitus 2,

Samankaltaiset tiedostot
58131 Tietorakenteet ja algoritmit (syksy 2015)

Tietorakenteet, laskuharjoitus 1,

Tietorakenteet, laskuharjoitus 3, ratkaisuja

Algoritmit 1. Demot Timo Männikkö

58131 Tietorakenteet ja algoritmit (kevät 2016) Ensimmäinen välikoe, malliratkaisut

58131 Tietorakenteet ja algoritmit (kevät 2014) Uusinta- ja erilliskoe, , vastauksia

f(n) = Ω(g(n)) jos ja vain jos g(n) = O(f(n))

Algoritmit 1. Demot Timo Männikkö

Nopea kertolasku, Karatsuban algoritmi

811312A Tietorakenteet ja algoritmit, , Harjoitus 3, Ratkaisu

1.4 Funktioiden kertaluokat

Johdatus diskreettiin matematiikkaan Harjoitus 5, Ratkaise rekursioyhtälö

11. Javan toistorakenteet 11.1

Kannan vektorit siis virittävät aliavaruuden, ja lisäksi kanta on vapaa. Lauseesta 7.6 saadaan seuraava hyvin käyttökelpoinen tulos:

Ohjelmointi 1 / 2009 syksy Tentti / 18.12

4 Tehokkuus ja algoritmien suunnittelu

Diskreetin matematiikan perusteet Laskuharjoitus 2 / vko 9

Algoritmit 1. Luento 2 Ke Timo Männikkö

= 5! 2 2!3! = = 10. Edelleen tästä joukosta voidaan valita kolme särmää yhteensä = 10! 3 3!7! = = 120

811312A Tietorakenteet ja algoritmit , Harjoitus 2 ratkaisu

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

1. (a) Seuraava algoritmi tutkii, onko jokin luku taulukossa monta kertaa:

A TIETORAKENTEET JA ALGORITMIT

Sekalaiset tehtävät, 11. syyskuuta 2005, sivu 1 / 13. Tehtäviä

Sisältö. 2. Taulukot. Yleistä. Yleistä

16. Ohjelmoinnin tekniikkaa 16.1

12. Javan toistorakenteet 12.1

(p j b (i, j) + p i b (j, i)) (p j b (i, j) + p i (1 b (i, j)) p i. tähän. Palaamme sanakirjaongelmaan vielä tasoitetun analyysin yhteydessä.

Sisällys. 17. Ohjelmoinnin tekniikkaa. Aritmetiikkaa toisin merkiten. for-lause lyhemmin

Sisältö. 22. Taulukot. Yleistä. Yleistä

12. Javan toistorakenteet 12.1

Tietorakenteet (syksy 2013)

ALGORITMIT 1 DEMOVASTAUKSET KEVÄT 2012

Reaalifunktioista 1 / 17. Reaalifunktioista

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 16.3

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

Tietorakenteet ja algoritmit - syksy

2.1. Tehtävänä on osoittaa induktiolla, että kaikille n N pätee n = 1 n(n + 1). (1)

Tekijä MAA2 Polynomifunktiot ja -yhtälöt = Vastaus a)

Miten osoitetaan joukot samoiksi?

Luku 8. Aluekyselyt. 8.1 Summataulukko

Sisällys. 16. Ohjelmoinnin tekniikkaa. Aritmetiikkaa toisin merkiten. Aritmetiikkaa toisin merkiten

ITKP102 Ohjelmointi 1 (6 op), arvosteluraportti

16. Ohjelmoinnin tekniikkaa 16.1

1. Esitä rekursiivinen määritelmä lukujonolle

Matematiikan tukikurssi, kurssikerta 5

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Algoritmi on periaatteellisella tasolla seuraava:

811312A Tietorakenteet ja algoritmit I Johdanto

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä

Esimerkkejä polynomisista ja ei-polynomisista ongelmista

2017 = = = = = = 26 1

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 15.3

Ohjelmoinnin perusteet, syksy 2006

Matematiikan tukikurssi

Matematiikan tukikurssi

Diskreetin matematiikan perusteet Laskuharjoitus 1 / vko 8

3. Laskennan vaativuusteoriaa

Harjoitustyön testaus. Juha Taina

811120P Diskreetit rakenteet

811120P Diskreetit rakenteet

2. Johdanto tietorakenteisiin

Vapaus. Määritelmä. jos c 1 v 1 + c 2 v c k v k = 0 joillakin c 1,..., c k R, niin c 1 = 0, c 2 = 0,..., c k = 0.

Ohjelmointi 2 / 2010 Välikoe / 26.3

Yhtälöryhmät 1/6 Sisältö ESITIEDOT: yhtälöt

58131 Tietorakenteet ja algoritmit Uusinta- ja erilliskoe ratkaisuja (Jyrki Kivinen)

Tarkennamme geneeristä painamiskorotusalgoritmia

Esitetään tehtävälle kaksi hieman erilaista ratkaisua. Ratkaisutapa 1. Lähdetään sieventämään epäyhtälön vasenta puolta:

(a) L on listan tunnussolmu, joten se ei voi olla null. Algoritmi lisäämiselle loppuun:

Johdatus lukuteoriaan Harjoitus 2 syksy 2008 Eemeli Blåsten. Ratkaisuehdotelma

2.2.1 Ratkaiseminen arvausta sovittamalla

Sisällys. 15. Lohkot. Lohkot. Lohkot

5. OSITTAISINTEGROINTI

Matematiikan tukikurssi, kurssikerta 3

MATEMATIIKAN KOE, PITKÄ OPPIMÄÄRÄ HYVÄN VASTAUKSEN PIIRTEITÄ

1 Kertaus. Lineaarinen optimointitehtävä on muotoa:

Funktiot. funktioita f : A R. Yleensä funktion määrittelyjoukko M f = A on jokin väli, muttei aina.

MS-A0401 Diskreetin matematiikan perusteet

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

Numeeriset menetelmät TIEA381. Luento 6. Kirsi Valjus. Jyväskylän yliopisto. Luento 6 () Numeeriset menetelmät / 33

Positiivitermisten sarjojen suppeneminen

Jokaisen parittoman kokonaisluvun toinen potenssi on pariton.

Algoritmit 1. Luento 13 Ti Timo Männikkö

Tietorakenteet ja algoritmit syksy Laskuharjoitus 1

MAB3 - Harjoitustehtävien ratkaisut:

Algoritmien suunnittelu ja analyysi (kevät 2004) 1. välikoe, ratkaisuja

Olkoon seuraavaksi G 2 sellainen tasan n solmua sisältävä suunnattu verkko,

verkkojen G ja H välinen isomorfismi. Nyt kuvaus f on bijektio, joka säilyttää kyseisissä verkoissa esiintyvät särmät, joten pari

1. Mitä tehdään ensiksi?

Matematiikan tukikurssi

Tietorakenteet, laskuharjoitus 7, ratkaisuja

ITKP102 Ohjelmointi 1 (6 op)

T Datasta tietoon, syksy 2005 Laskuharjoitus 8.12., ratkaisuja Jouni Seppänen

Kohdissa 2 ja 3 jos lukujen valintaan on useita vaihtoehtoja, valitaan sellaiset luvut, jotka ovat mahdollisimman lähellä listan alkua.

R : renkaan R kääntyvien alkioiden joukko; R kertolaskulla varustettuna on

MAB3 - Harjoitustehtävien ratkaisut:

MATEMATIIKAN KOE, PITKÄ OPPIMÄÄRÄ HYVÄN VASTAUKSEN PIIRTEITÄ

58131 Tietorakenteet ja algoritmit (syksy 2015) Toinen välikoe, malliratkaisut

Similaarisuus. Määritelmä. Huom.

Transkriptio:

Tietorakenteet, laskuharjoitus, 6.-9.1 Muista TRAKLA-tehtävien deadline 31.1. 1. Tarkastellaan ensin tehtävää yleisellä tasolla. Jos funktion T vaativuusluokka on O(f), niin funktio T on muotoa T (n) = cf(n) + dg(n), missä g = O(f) ja c sekä d ovat vakiokertoimia. Ehto g = O(f) seuraa siitä, että muulloin T O(f). Tehtävänannon nojalla voidaan jättää funktio g huomioimatta. Itse asiassa tämä rajoitus on oleellinen, sillä ilman sitä olisi mahdotonta saada yksikäsitteisiä ratkaisuja tämän tehtävän kohtiin. Näiden havaintojen nojalla jokaisessa tehtävän kohdassa riittää ratkaista yhtälöstä cf(00) = 1 ms vakiokerroin c ja laskea sen jälkeen arvo lausekkeelle cf(5000), josta nähdään kuinka monta millisekuntia kullakin vaativuudella kuluisi aikaa syötteen käsittelyyn, jonka koko on 5000. (a) O(log n): Käsitellään edellinen päättely vielä tässä erikoistapauksessa, jotta ajatus tulisi selkeämmäksi konkreettisen esimerkin avulla. Algoritmin aikavaativuus on O(log n), joten sen vaativuutta tarkasti kuvaava funktio on muotoa c log n + dg(n), jossa d on vakio ja g(n) on jokin funktio, jolle pätee g(n) = O(log n). Edellä käsitellyn yleisemmän päättelyn merkinnöin f = log. Koska g voitiin jättää huomiotta riittää ratkaista c log 00 = 1. c log 00 = 1 ms c = 1 ms log 00 Löydettiin c:lle arvo. Nyt voidaan laskea kauan suoritus kestäisi kun n = 5000. Huomaa, että tässä vaiheessa ei vielä oltu kiinnitetty logaritmin kantalukua. Käyttämällä logaritmin kannanvaihtosääntöä log a x = log b x log b a osoittautuukin, ettei se ole lainkaan välttämätöntä. Siis olkoon a > 1. c log a 5000 = log a 5000 log a 00 ms = log 00 5000 ms 1, 61 ms Havaittiin, että algoritmi on lähes yhtä nopea 5000:n kokoiselle syötteelle, kuin 00:nkin kokoiselle syötteelle. Tämän laskun perusteella logaritmisen aikavaativuuden algoritmit vaikuttavat hyvin tehokkailta. (b) O(n): Ratkaistaan ensin c tunnetun arvon nojalla. c00 = 1 ms c = 1 ms 00 Nyt voidaan laskea algoritmin kesto 5000:n kokoiselle syötteelle. c5000 = 5000 ms 00 = 5 ms 1

(c) O(n log n): Tämä lasketaan kuten edelliset kohdat. Suoritusaika, kun n = 5000: c5000 log 5000 = (d) O(n ): Ratkaistaan c: Suoritusaika, kun n = 5000: c00 log 00 = 1 ms c = c5000 = 5000 log 5000 ms 00 log 00 1 ms 00 log 00 c00 = 1 ms c = 1 ms 40000 5000000 ms 40000 = 5 log 00 5000 ms 40, 19 ms = 65 ms = 0, 65 s Havaitaan, että neliöllisen aikavaativuuden algoritmeilla suoritus alkaa jo hidastua tuntuvasti. (e) O( n ): Ratkaistaan c: c 00 = 1 ms c = 1 ms 00 Suoritusaika, kun n = 5000: c 5000 = 5000 ms 00 = 4800 ms Tälläisenään luku ei kerro vielä juuri mitään. Yhdessä vuodessa on 365 4 60 60 1000 = 31536000000 ms ja log 31536000000 34, 876, joten algoritmin suoritus vie aikaa noin 4765, 558 10 1434 vuotta. Eräiden arvioiden mukaan maailmankaikkeudessa on atomeja noin 10 80 kappaletta. Samaisen lähteen mukaan maailmankaikkeuden ikä on vaivaiset 13, 7 10 9 vuotta, joten suorittaaksemme näin kauan kestävän algoritmin tarvitsisimme aikaa vähintään 00 kertaa maailmankaikkeuden iän verran. Tämän tarkastelun nojalla eksponentiaalisen aikavaativuuden algoritmi vaikuttaa hyvin pitkälti käyttökelvottomalta erittäin pienestä vakiokertoimesta huolimatta. Käytännössä eksponentiaalisen aikavaativuuden algoritmeja tulisikin välttää viimeiseen asti. Joskus niitä on pakko käyttää, mutta tällöin on varmistuttava, että mahdolliset syötteet ovat tarpeeksi pieniä.. Yksi minuutti sisältää 60 1000 = 60000 ms. Tehtävässä voidaan käyttää hyväksi edellä ratkottuja vakiokertoimia. Jokaisessa kohdassa riittää nyt etsiä suurin n:n arvo, joka toteuttaa epäyhtälön cf(n) 60000 ms. (a) O(log n): log a n ms log a 00 60000 ms log 00 n 60000 n 00 60000 6, 3 10 138061 Huomataan, että logaritmisen aikavaativuuden algoritmille voidaan antaa käytännössä kuinka iso syöte tahansa, jos jaksetaan odotella vähän aikaa.

(b) O(n): n ms 00 60000 ms n 00 60000 = 1, 107 Myös lineaarisen ajan vievä algoritmi sietää vielä hyvin suuria syötteitä. (c) O(n log n): n log a n ms 00 log a 00 60000ms n log a n log a 00 1000000 n log 00 n 1000000 Edellä olevaa epäyhtälöä ei kyetä ratkaisemaan analyyttisesti ainakaan tämän kurssin esitiedoilla. Kokeilemalla havaitaan, että suurin kokonaisluku, jolla epäyhtälö on vielä voimassa on 4170906. (d) O(n ): Käytetään jälleen edellisessä kohdassa ratkaistun vakiokertoimen c arvoa hyväksi. (e) O( n ): n ms 40000 60000 ms n 400000000 n 400000000 48989, 79 n ms 00 60000 ms n 00 60000 log n 00 log 60000 n 00 log 60000 n 00 + log 60000 15, 87 Eksponentiaalisen aikavaativuuden algoritmissa syötteen ei tarvitse olla kovinkaan suuri, jotta suoritusaika hidastuu. Todellisissa tapauksissa vakiokertoimet eivät ole niin pieniä kuin tässä tapauksessa. Esimerkiksi vakiokertoimella c = 1 algoritmille voitaisiin antaa korkeintaan 15:n kokoinen syöte, mikäli haluttaisiin laskennan suoriutuvan alle minuutissa. 3. Muistutetaan tässä, että funktio f kuuluu kertaluokkaan O(g), jos on olemassa vakiot d > 0 ja n 0 siten että kaikilla n > n 0 pätee f(n) dg(n). Tätä merkitään f = O(g). (a) Näytetään, että n + 7n + 3 = O(n 3 ). Tässä on ideana arvioida annettua funktiota sopivalla tavalla ylöspäin. Sopiva tapa määräytyy kulloisenkin tavoitteen mukaan. Tässä tehtävässä halutaan osoittaa funktion vaativuusluokaksi O(n 3 ), joten ylärajaksi pitäisi saada d n 3, jollain d > 0. Olkoon n > 0. n + 7n + 3 n + 7n + 3n n + 7n + 3n = 1n 1n 3 Edellinen laskussa osoitettiin, että n + 7n + 3 1n 3 kun n > 0, siis määritelmän vakioiksi kelpaavat n 0 = 0 ja d = 1. 3

(b) Näytetään, että n 3 + 7n + 3 O(n ). Todistetaan tämä vastaoletuksen avulla. Oletetaan siis, että n 3 + 7n + 3 = O(n ). Olkoon d ja n 0 määritelmän takaamat vakiot, joille pätee vastaväitteen nojalla n 3 + 7n + 3 dn kaikille n > n 0. Arviomalla funktiota alaspäin kun n > n 0 > 0 saadaan: n 3 n 3 n 3 + 7n + 3 dn Jakamalla puolittain luvulla n tästä seuraa, että n d kaikilla n > n 0 0. Tämä ei voi päteä koska lukua n voidaan kasvattaa rajatta. Saatiin aikaiseksi ristiriita, joten vastaoletuksen on oltava väärä. Saatiin siis todistettua n 3 + 7n + 3 O(n ). Edellisessä päättelyssä päästiin tulokseen, josta seuraa ristiriita, mutta näytetään vielä matemaattisen täsmällisyyden nimissä kaksi erilaista tapaa kaivaa ristiriita edellisestä lausekkeesta. Kummassakin on ajatuksena valita n:lle jokin arvo, jolla vastaväitteen mukaan pitäisi päteä n d. Valintaa n:n arvoksi rajoittaa ehto n > n 0. Saavuttaaksemme ristiriidan halutaan myös että n > d. Erääksi ristiriitaan johtavaksi arvoksi kelpaa n = max{n 0, d + 1. Tästä seuraa kaksi vaihtoehtoa, jotka kummatkin on käsiteltävä erikseen. Käsitellään ensin tapaus d > n 0. Tällöin n = d + 1 ja edellä johtamamme epäyhtälö väittää d + 1 d 1 0, joka on ilmiselvä ristiriita. Toisessa tapauksessa n 0 d, jolloin saadaan edellä olevan nojalla Siis pääsimme jälleen ristiriitaan. n 0 + 1 d n 0 n 0 + 1 n 0 1 0 Esitetään vielä toinen sopiva arvo n:lle, jonka avulla päädytään ristiriitaan. Asetetaan n = (n 0 + 1)(d + 1). Tätä hiukan yllättävää valintaa puoltaa havainto, että d voi olla kuinka pieni positiivinen luku tahansa. Lisäämällä d:hen 1 ja kertomalla n 0 +1 tällä luvulla voidaan olla varmoja, että kaikissa mahdollisissa tapauksissa n > n 0. Sijoittamalla tämä arvo edellä johdettuun epäyhtälöön, päästään haluttuun tulokseen. (n 0 + 1)(d + 1) d (n 0 + 1)d + n 0 + 1 d (n 0 + 1)d (n 0 + 1)d + n 0 + 1 d n 0 + 1 1 1 < n 0 + 1 1 1 < 1 Nähtiin, että myös tällä tavoin saavutetaan ristiriitan kohtuullisen yksinkertaisen laskennon jälkeen. (c) Näytetään, että log n O(10 16 ). Käytetään jälleen vastaoletusta, siis oletetaan, että log n = O(10 16 ). On siis olemassa vakiot d 0 ja n 0 s.e. log n d 0 10 16 = d 0 10 16 1. Merkitään d = d 0 10 16. Nyt log a n d n a d, joka on selvästikin ristiriita n:n arvolla (n 0 +1)(a d +1). Siis alkuperäinen väite pitää paikkansa. 4

(d) Osoitetaan, että 10 6 = O(1). Kun valitaan määritelmän d:ksi esimerkiksi 10 7, niin kaikilla n pätee 10 6 d 1 = 10 7 1, joten n 0 :ksi kelpaa mikä tahansa luku. Kuten huomataan n ei vaikuta tähän vaativuusluokkaan kuuluvien funktioiden arvoon millään tavalla. Algoritmin aika- tai tilavaativuutena tämä tarkoittaa sitä, että syötteen koko ei vaikuta algoritmin suoritusaikaan tai sen käyttämään muistiin millään tavalla. Toisin sanoen algoritmin käyttämä aika tai tila on saman kokoinen kaikilla syötteillä. Tälläisiä algoritmeja kutsutaan vakioaikaisiksi tai sanotaan että algoritmi käyttää vakiomäärän muistia. (e) Osoitetaan, että log n = O(log n). Intuiitiivisesti väite on selvä, sillä eksponentti saadaan tuotua logaritmin sisältä logaritmin kertoimeksi. Käsitellään tämä kuitenkin hiukan yksityiskohtaisemmin. Käytetään logaritmeille mielivaltaisia kantalukuja a, b > 1 havainnollistaaksemme miksi aikavaativuusmerkinnöissä ei tarvitse kiinnittää logaritmin kantaa. Logaritmin laskusäännöistä tiedetään, että log a n = log a n = log b n log b a = log b a log b n Tämä arvio antaa määritelmän d:tä vastaavan luvun valitsemiseksi hyvän idean. Asetetaan d = 3 log b a. Nyt voidaan helposti osoittaa näyttää väite todeksi. log b a 3 log b a log b a log b n 3 log b a log b n kaikilla n > 0 log b n log b a 3 log b a log b n kaikilla n > 0 log a n 3 log b a log b n kaikilla n > 0 Tämä riittää osoittamaan väitteen. Korvaamalla laskuista numero k:lla ja 3 k + 1:llä oltaisiin todistettu log n k = O(log n). 4. Tarkastellaan seuraavaa lukujen 1,..., n summan laskevaa algoritmia. Summa(n) 1 summa = 0 for i = 1 to n // Invariantti: summa == i 1 j 3 summa = summa + i Tarkastellaan aluksi algoritmin aikavaativuutta. Rivilla 1 oleva sijoitus suoritetaan ainoastaan kerran koko algoritmin avulla. Tavallinen sijoitus sujuu vakioajassa. 5

Rivillä oleva silmukan tarkistus suoritetaan n + 1 kertaa. Itse tarkistus sujuu vakioajassa. Usein algoritmien analyysissa ajatellaan for-silmukoiden kätkevän taakseen while-silmukan kaltaisen rakenteen, jota seuraava koodin pätkä kuvaa. i = 0 while i < n i = i + 1... Tässä silmukassa while:n tarkistus suoritetaan selvästikin n + 1 kertaa. Esimerkiksi C-kielen tai Javan for-silmukoista on helposti nähtävissä samankaltaisuus while-silmukkaan. Rivi 3 suoritetaan tasan n kertaa. Jälleen itse rivillä suoritettava yhteenlasku kestää ainoastaan vakioajan. Jo tämän tarkastelun nojalla nähdään, että algoritmi vie lineaarisen ajan syötteen koon suhteen, kun ajatellaan koon tarkoittavan tässä yhteydessä argumenttina saatavaa numeroa. Osoitetaan vielä hiukan seikkaperäisemmin miksi algoritmin aikavaativuus on luokkaa O(n). Merkitään rivin i suoritukseen kuluvaa aikaa a i :llä. Kun n > 0 algoritmin viemää aikaa voidaan arvioida seuraavasti: a 1 + (n + 1)a + na 3 = a 1 + a + (a + a 3 )n a 1 n + a n + (a + a 3 )n = (a 1 + a + a 3 )n. Joten algoritmin aikavaativuutta kuvaava funktio on kaikilla n > 0 pienempi tai yhtäsuuri kuin dn, missä d = a 1 + a + a 3. Algoritmin tilavaativuus on vakio, siis luokkaa O(1), sillä olipa n minkä kokoinen tahansa, algoritmi tarvitsee ainoastaan yhden muuttujan. Tarkastellaan vielä algoritmin pseudokoodiesitykseen merkittyä invarianttia. Aloitettaessa silmukan ensimmäinen kierros i = 1. Invariantti väittää, että muuttuja summa arvo on i 1 j = 0 j = 0. Tämä pitää paikkansa, sillä muuttujaan summa on vielä koskematon alustuksen jäljiltä. Jos invariantti oli voimassa kun i = k, niin se pätee myös kun i = k + 1. Tällöin invariantti väittää, että muuttujan summa arvo on i 1 j = k+1 1 j = k j. Koska invariantti oli voimassa kun i = k, niin summan arvo on tämän nojalla seuraavalla kierroksella summa + k = k 1 j + k = k j = i 1 j, siis täsmälleen se mitä invariantti väittää kun i = k+1. Edellisen kaavan k tulee siitä, että kullakin kierroksella summaan lisätään i:n arvo. Saavuttaessa viimeisellä kierroksella i:n arvoa testaavaan silmukkaan pätee, että i = n+1. Edellä osoitettiin, että invariantti pätee myös tällöin, joten muuttujan summa arvoksi saatiin silmukan päätyttyä i 1 j = n j = 1 + +... + n, eli juurikin se mitä algoritmilla haluttiin saavuttaa. 5. Tehtävän oli tutkia algoritmia Evaluate-Polynomial. 6

Evaluate-Polynomial(A[0.. k], x) 1 s = 0 for i = 0 to A.length // Invariantti: s == i 1 A[j] xj 3 z = 1 4 for j = 1 to i 5 z = z x 6 s = s + A[i] z 7 return s Simuloidaan ensin algoritmin toimintaa funktiolla p(x) = x 3 3x 7 kun x =. Algoritmin alkutila: s == 0, i = 0, A[i] = 7 Tilanne ensimmäisen kierroksen jälkeen: s == 7, i = 1, A[i] = 0 Tilanne toisen kierroksen jälkeen: s == 7, i =, A[i] = 3 Tilanne kolmannen kierroksen jälkeen: s == 19, i = 3, A[i] = Tilanne viimeisen kierroksen jälkeen: s == 3, i = 4 Merkitään n = A.length 1, joka on luonnollinen mitta syötteen koolle. Rivi 1 suoritetaan kerran. Rivi suoritetaan n + 1 kertaa. operaatioita. Rivi 3 suoritetaan n kertaa. Rivi 4 suoritetaan jokaisella ulomman silmukan kierroksella i + 1 kertaa. Koko algoritmin aikana tämä rivi suoritetaan kertaa. n+1 0 +... + (n + 1) = i = i=0 (n + 1)(n + ) = O(n ) Rivi 5 suoritetaan yhden ulomman silmukan kierroksella i kertaa. Yhteensä tämä suoritetaan n(n+1) kertaa. Rivi 6 suoritetaan yhteensä n kertaa. Rivi 7 suoritetaan ainoastaan kerran. Koska aritmeettisten operaatioiden ajatellaan olevan vakioaikaisia nähdään ylläolevasta päättelystä, että algoritmin suoritusaika on O(n ). Tämä voidaan edellisen kohdan tapaan perustella seikkaperäisesti laskemalla algoritmin käyttämä aika joillain ajoilla a i. 6. (a) Summakaavan n i=1 i arvoksi tiedetään n(n+1). Puuttuva arvo voidaan selvittää laskemalla taulukon arvot yhteen ja vähentämällä saatu tulos ylläolevan kaavan arvosta. Esitetään ratkaisu vielä pseudokoodilla. 1 Lukua n 1 kutsutaan polynomin asteeksi. 7

Etsi_puuttuva(A[1.. n]) 1 summa = 0 for i = 1 to A.length 3 summa = summa + A[i] 4 n = A.length + 1 5 return (n (n + 1))/ summa (b) Koska tietorakenteen ainoa tarvittava operaatio on osasumma riittää tallettaa lukujen summat taulukkoon S. Jos rakenne alustetaan antamalla sille taulukko A, niin tällöin S[i] = i A[j]. osasumma(a, b) saadaan laskettua vakioaikaisesti erotuksena S[b] S[a 1] ja alustus vie lineaarisen ajan. Ohessa on tietorakenteen Java-luokkana sekä sen käyttöä esittelevä pääohjelma. public class Osasummat { private double[] summat; public Osasummat(double[] luvut) { this.summat = new double[luvut.length]; this.summat[0] = luvut[0]; for(int i = 1; i < luvut.length; i++) { this.summat[i] = this.summat[i-1] + luvut[i]; public double osasumma(int i,int j) { if (j >= this.summat.length) j = this.summat.length-1; if (i > 0) return this.summat[j] - this.summat[i-1]; else return this.summat[j]; class T6b { /* Metodi ottaa taulukkojen koon komentoriviparametrinaan. */ public static void main(string[] args) { if (args.length < 1) System.exit(0); System.out.println("foo"); int koko = Integer.parseInt(args[0]); // Talletetaan tähän taulukkoon luvut 0...n double[] taulu = new double[koko]; // Tähän approksimoidaan funktion x^ integraalin arvoa // välillä [0,1] double[] integraalit = new double[koko]; 8

double vali = (1.0/koko); for(int i = 0; i < koko; i++) { taulu[i] = i; integraalit[i] = vali*(math.pow(i/(double)koko+0.5*vali,)); Osasummat summat = new Osasummat(taulu); Osasummat integraali = new Osasummat(integraalit); System.out.println(summat.osasumma(0,koko - 1)); System.out.println(summat.osasumma(0,koko/)); System.out.println(summat.osasumma(koko/,koko)); System.out.println(integraali.osasumma(0,koko - 1)); System.out.println(integraali.osasumma(0,koko/)); System.out.println(integraali.osasumma(koko/,koko)); 9