58131 Tietorakenteet ja algoritmit (kevät 2014) Uusinta- ja erilliskoe, 10..2014, vastauksia 1. [9 pistettä] (a) Todistetaan 2n 2 + n + 5 = O(n 2 ): Kun n 1 on 2n 2 + n + 5 2n 2 + n 2 +5n 2 = 8n 2. Eli voidaan valita vakioiksi n 0 = 1 ja d = 8. (b) Todistetaan 2n 2 + n + 5 = Ω(n 2 ): Kun n 1 on n 2 + n + 5 n 2. Eli voidaan valita vakioiksi n 0 = 1 ja d = 1. (c) Väite 3n 3 + n + 5 = O(n 2 ) ei pidä paikkaansa: Jos n 1, niin 3n 3 + n+5 > 3n 3. Nyt pitäisi olla olemassa vakiot d ja n 0 1, joille pätevät 3n 3 +n+5 dn 2, kun n n 0 ja silloin myös 3n 3 < dn 2, eli jakamlla n 2 saadaan 3n < d. Valitsemalla n = max{d,n 0 } saamme 3d < d, joka on ristiriita. 2. [10 pistettä] Käytetään apuosoittimia, jotka osoittavat kullakin hetkellä listan käsiteltävän solmun edeltäjään (prev) ja seuraajaan (seur). Algoritmin on toimittava myös tapauksissa, joissa alkioiden määrä on 0 tai 1 (jolloin ei tarvitse tehdä mitään). Reverse(L) if L NIL and L.next NIL edel = nil seur = L.next while seur NIL L.next = edel edel = L L = seur seur = L.next L.next=edel return L Algoiritmi käy läpi listan alusta loppuun suorittaen kullekin solmulle vakioaikaiset operiaatiot, eli aikavaativuus on O(n). Käytetään kaksi apumuuttujaa, joten tilavaativuus on O(1). 3. [11 pistettä] (a) [3 pistettä] Solmut esijärjestyksessä ovat 4, 2, 1, 3, 7,, 10, 9, 11; sisäjärjestyksessä 1, 2, 3, 4,, 7, 9, 10, 11; jälkijärjestyksessä 1, 3, 2,, 9, 11, 10, 7, 4.
(b) [8 pistettä] Lisätään alkio 12 LeftRotate(7) Lisätään alkio 8. RightLeftRotate(4) 4 2 7 1 3 10 9 11 \ 12 4 \ 9 12 4 \ 9 12 / 8 7 4 10 2 9 11 1 3 8 12
Poistetaan alkio 4. 7 10 / 2 9 11 1 3 8 12 RightRotate() 7 1 9 11 / 3 8 12 Tarkastellaan sitten mitä tapahtuisi jos operaatiot olisivat päinvastaisessa järjestyksessä. Ensin poistetaan 4, jolloin vaihdetaan sen paikalle seuraaja. LeftRotate(7) 2 7 \ 1 3 10 9 11 \ 9
Lisätään alkio 8. \ 9 / 8 RightLeftRotate(7) 1 3 8 11 7 9 Lisätään alkio 12 1 3 8 11 \ 7 9 12 Ei tarvitse tehdä mitään rotaatioita. 4. [12 pistettä] Tehtävät ovat olleet pajatehtävinä, tosin pajassa ei sallittu (a)- kohdassa samaa lukua moneen kertaan. (a) [4 pistettä] Oletetaan taulukon A sisältävän alkiot a 1,...,a n. Taulukko voidaan järjestää ajassa O(n log n) käyttäen kekojärjestämistä tai lomitusjärjestämistä. Asetetaan tämän jälkeen osoittimet i ja j taulukon alkuun ja loppuun. Jos näiden osoittamien alkioiden summa on pienempi kuin k, kasvatetaan osoitinta i yhdellä. Jos se on suurempi, pienennetään osoitinta j yhdellä. Silmukka suoritetaan n kertaa, mutta sen suorittaminen vie vakioajan, joten aikavaativuus on kokonaisuudessaan O(nlogn+n) = O(nlogn).
find-two-terms(a, n, k) A = sort(a) // kekojärjestäminen tai lomitusjärjestäminen return find-terms(a, n, k) find-terms(a, n, k) i = 1 j = n while i j sum = A[i] + A[j] if sum = k return true if sum < k i = i + 1 if sum > k j = j - 1 return false Oikeellisuustodistusta ei pyydetty, mutta osoitamme että ratkaisu on oikea. Jos algoritmi ylipäänsä palauttaa arvon true, selvästi tämän tuottama pari täyttää ehdot. Pitää vielä osoittaa, että algoritmi todella löytää kelvollisen parin, jos sellainen on olemassa. Oletetaan siis, että joillakin i ja j pätee A[i ]+A[j ] = k. Voidaan valita i j. Osoitetaan, että silmukka pitää voimassa invariantin i i ja j j. Ennen silmukkaan tuloa tämä selvästi pätee. Oletetaan nyt, että silmukassa ehdot i i ja j j pätevät. Jos sum = k, algoritmi päättyy oikeaan tulokseen. Jos sum < k, niin oletuksesta j j seuraa taulukon järjestyksen nojalla A[j ] A[j]. Siis A[i] = sum A[j] < k A[j] koska sum < k k A[j ] koska A[j] A[j ] = A[i ] koska A[i ]+A[j ] = k. Taulukon järjestyksen nojalla siis i < i, joten ehto i i pysyy voimassa myös sijoituksen i = i+1 jälkeen. Tapaus sum > k käsitellään vastaavasti. Siis invariantti i i j j pysyy voimassa. Erityisesti siis aina i j eli while-lauseen ehto ei koskaan tule epätodeksi. Silmukka ei kuitenkaan voi pyöriä ikuisesti, sillä erotus j i pienenee joka iteraatiolla eikä koskaan mene nollan alapuolelle. Siis algoritmin suoritus pysähtyy return-lauseeseen silmukan sisällä, jolloin palautettava tulos on oikea.
(b) [4 pistettä] Hyödynnetään taas funktiota find-terms kutsumalla sitä erikseen jokaisen taulukon A alkion kohdalla. Sen aikavaativuus oli O(n), ja sitä kutsutaan silmukassa n kertaa, mutta järjestäminen tarvitsee suorittaa vain kerran. Siksi algoritmin kokonaisaikavaativuus ono(n 2 +nlogn) = O(n 2 ). find-three-terms(a, n, k) A = sort(a) // kekojärjestäminen tai lomitusjärjestäminen for i = 1 to n find-terms(a,n,k-a[i]) return false (c) [4 pistettä] Muodostetaan kaikki n 2 kahden luvun summaa taulukkoon B ajassa O(n 2 ). Nyt voidaan taas käyttää funktiota find-two-terms. KoskaB sisältään 2 alkiota, kuluu aikaao(n 2 logn 2 ) = O(n 2 2 logn) = O(n 2 logn). find-four-terms(a, n, k) for i = 1 to n for j = 1 to n B[n*(j-1)+i] = A[i]+A[j] find-two-terms(b,n*n,k) 5. [8 pistettä] (a) Dijkstra etsii lyhimmät polut tietystä solmusta verkossa. Dijkstan algoritmissa ei saa olle negatiivisia kaarenpainoja. Dijkstra soveltuu sekä suunnatuille että suuntaamattomille verkoille (b) Floyd-Warshall etsii lyhimmät polut kaikista solmuista kaikkiin solmuihin verkossa. (c) Ensin kaikkien solmujen etäisyydet ovat, paitsi a:n joka on 0. Valitaan solmu a ja päivitetään etäisyydet: b 14 ja f 2. Jäljellä olevista solmuista pienin etäisyysarvio on f:llä eli 2 joten valitaan se seuraavaksi ja päivitetään etäisyys e 7 (a:n etäisyyttä ei päivitetä). Jäljellä olevista pienin on e ja päivitetään b 12, d 9. Jäljellä olevista pienin on d ja päivitetään c 10. Jäljellä olevista pienin on c ja päivitetään b 11. Jäljellä on vain b ja olemme valmiit. Lopulliset etäisyydet ovat: b 11, c 10, d 9, e 7, f 2.
. [10 pistettä] Ehdotettu ratkaisumenetelmä toimii oikein. Todistus: Olkoon (V, T) jokin pienin virittävä puu ja p maksimipainoltaan pienin polku s t puun kaaria pitkin. Tehdään vastaoletus, että verkossa on olemassa maksimipainoltaan pienempi polku p solmusta s solmuun t. Valitaan polun p painavin kaari; olkoon se e. Tarkastellaan verkkoa (V,T {e}). Verkossa on kaksi komponenttia, joista toinen sisältää solmun s ja toinen solmun t. Polku p sisältää ainakin yhden kaaren e, joka yhdistää näitä komponentteja. Siis (V,T {e } {e}) on virittävä puu. Oletuksen mukaan kaikki polun p kaaret ovat kevyempiä kuin e. Erityisesti tämä koskee kaarta e, joten w(t {e } {e}) = w(t)+w(e ) w(e) < w(t). Siis verkolla on pienempikin virittävä puu kuin (V,T); ristiriita.