UNIVERSITY OF OSLO Faculty of mathematics and natural sciences Examination in INF2220 — Algorithms and data structures Day of examination: 15. desember 2010 Examination hours: 14.30 – 18.30 This problem set consists of 8 pages. Appendices: None Permitted aids: All printed and written Please make sure that your copy of the problem set is complete before you attempt to answer anything. This is the English version of the solutions for the exam. Binary Tree (weight 15%) Problem 1 1a Insert Nodes (weight 5%) 9 10 1 3 4 6 7 8 Figure 1: Solution 1b Logarithmic time (weight 5%) No it’s not possible since the tree is out of balance, it contains 8 elements, log2 (8) = 3, the tree is higher than that. (Continued on page 2.) Examination in INF2220, 15. desember 2010 1c Page 2 Remove Nodes (weight 5%) 9 10 4 6 7 8 Figure 2: Solution Note As long as the binary search tree, still is a binary search tree after the nodes have been removed, this assignment should be ok. Different removal schemes may lead to different trees. (Continued on page 3.) Examination in INF2220, 15. desember 2010 Problem 2 2a Page 3 Sorting (weight 20%) Classification (weight 5%) It is value based, no comparison of the elements are ever done, we just allocate buckets for all possible values and update how many elements that fall into each bucket. 2b Time Complexity (weight 5%) The first loop: O(n, m) = n for ( int i = 0 ; i < input . length ; i ++ ) { i f ( input [ i ] > max ) { max = input [ i ] ; } } The second loop: O(n, m) = n for ( int i = 0 ; i < input . length ; i ++ ) { b [ input [ i ] ] + + ; } The third loop: O(n, m) = m + n for ( int i = 0 ; i < b . length ; i ++ ) { while ( b [ i ] > 0 ) { s o r t [ counter ] = i ; b [ i ]−−; counter ++; } } NOTE The inner while loop can only be executed n times, since we can fill at most n buckets. Total time complexity: O(n, m) = n + n + m + n = 3n + m (linear time complexity: n). As bigO, they could state O(n, m) = O(n + m) with constants and so on removed, and with n, m → ∞ this leads to O(2n) → O(n). 2c Average case (weight 5%) The average case time complexity is identical to the worst case complexity, no matter what values our input array holds, the exact same steps are preformed. (Continued on page 4.) Examination in INF2220, 15. desember 2010 Page 4 Weakness (weight 5%) 2d The major weakness with this type of bucket sort is that large values requires you to allocate a very large array, i.e., the bucket array. If you want to sort an array of 2 elements, and one of the elements have a value of 1000000, you need to allocate an int array with 1000000 elements. Problem 3 3a Huffman Coding (weight 10%) Huffman tree (weight 10%) a c b d f e NOTE There are more than one legal Huffman tree, but a and c should get the shortest paths, and e and f should get the longest paths. (Continued on page 5.) Examination in INF2220, 15. desember 2010 Problem 4 4a Page 5 Parsed Expression (weight 25%) String representation (weight 5%) String s t r ( ) { i f ( isLeaf ( ) ) { return token ; } else { return String . format ( " (%s %s %s ) " , l e f t . s t r ( ) , token , r i g h t . s t r ( ) ) ; } } 4b Evaluate (weight 5%) double eval ( ) { i f ( isLeaf ( ) ) { return Double . parseDouble ( token ) ; } else { i f ( token . equals ( " + " ) ) { return l e f t . eval ( ) + r i g h t . eval } else i f ( token . equals ( "−" ) ) { return l e f t . eval ( ) − r i g h t . eval } else i f ( token . equals ( " * " ) ) { return l e f t . eval ( ) * r i g h t . eval } else { // token . equals ( " / " ) ) return l e f t . eval ( ) / r i g h t . eval } } } 4c (); (); (); (); Polish Notation (weight 5%) String p o l i s h ( ) { i f ( isLeaf ( ) ) { return token ; } else { return String . format ( "%s %s %s " , token , l e f t . p o l i s h ( ) , r i g h t . p o l i s h ( ) ) ; } } (Continued on page 6.) Examination in INF2220, 15. desember 2010 Page 6 Polish Calculator (weight 10%) 4d public double po lish Eva l ( String e xpr ess io n ) { String [ ] tokens = e xpr ess io n . s p l i t ( " " ) ; // made a l i t t l e s t a c k implementation here // but java . u t i l . Stack <String > should do : −) StrStack estack = new StrStack ( tokens . length + 1 ) ; StrStack unused = new StrStack ( tokens . length + 1 ) ; for ( int i = tokens . length − 1 ; i >= 0 ; i −−){ unused . push ( tokens [ i ] ) ; } String v1 , v2 , op ; while ( unused . hasMore ( ) ) { estack . push ( unused . pop ( ) ) ; while ( estack . s i z e ( ) > 2 ) { v1 = estack . pop ( ) ; v2 = estack . pop ( ) ; i f ( notOp ( v1 ) && notOp ( v2 ) ) { op = estack . pop ( ) ; estack . push ( strOp ( op , v1 , v2 ) ) ; } else { estack . push ( v2 ) ; estack . push ( v1 ) ; break ; } } } return Double . parseDouble ( estack . pop ( ) ) ; } Problem 5 5a Miscellancious (weight 15%) Topological sort (weight 7.5%) Assume that you have a dependency graph with the following nodes: {Q, B, J, P, A, Z}. There are only 4 legal topological orderings of the graph, which are listed below. (Continued on page 7.) Examination in INF2220, 15. desember 2010 J B Q P A 5b Z Boyer Moore (weight 7.5%) Calculate the good-suffix-shift for the needle: skjeskj goodshift[0] goodshift[1] goodshift[2] goodshift[3] goodshift[4] goodshift[5] goodshift[6] : : : : : : : !j !kj !skj !eskj !jeskj !kjeskj !skjeskj (Continued on page 8.) 1 7 7 4 4 4 4 Page 7 Examination in INF2220, 15. desember 2010 Problem 6 Page 8 Common Subset (weight 15%) Implementation (weight 10%) 6a s t a t i c char [ ] both ( char [ ] a1 , char [ ] a2 ) { final int CHAR_MAX = 256; int count = 0 ; int [ ] cache = new int [CHAR_MAX] ; // assume 1−b y t e i n i t i a l i z e d t o 0 // loop 1 for ( int i = 0 ; i < a1 . length ; i + + ) { i f ( cache [ ( int ) a1 [ i ] ] == 0 ) { cache [ ( int ) a1 [ i ] ] + + ; } } // loop 2 for ( int i = 0 ; i < a2 . length ; i + + ) { i f ( cache [ ( int ) a2 [ i ] ] > 0 ) { count ++; cache [ ( int ) a2 [ i ] ] = −1; } } int tmp = 0 ; char [ ] r e s u l t = new char [ count ] ; // loop 3 for ( int i = 0 ; i < CHAR_MAX; i + + ) { i f ( cache [ i ] == −1 ) { r e s u l t [ tmp++] = ( char ) i ; } } return r e s u l t ; } 6b Complexity (weight 5) • loop 1: N • loop 2: M • loop 3: 256 (constant) • O(N, M ) = N + M + 256 • O(N, M ) = N + M (Ignoring constants) • As N, M → ∞ we get O(N, M ) → O(2N ) → O(N ) • Linear time complexity