Examens Eng PDF
Examens Eng PDF
Examens Eng PDF
COLLECTION OF EXAMS
Albert Atserias
Amalia Duch
Enric Rodrı́guez Carbonell
(Editors)
2 Lab Exams 73
3 Final Exams 81
Problem 1 (3 points)
As graphs, all trees are planar. In particular this means that they are all representable on a
sufficiently large rectangular grid in such a way that the edges do not intersect (except at the
vertices, obviously). Here are two planar representations of a full binary tree with 16 leaves:
(1 point) Following the recursive pattern of the first representation, give recurrences for
the height H (n) and width W (n), respectively, of the grid that is needed to represent a full
binary tree with 2n leaves in this representation.
✬ ✩
✫ ✪
(1 point) Following the recursive pattern of the second representation, give the recurrence
for the length L(n) of the square grid that is needed to represent a full binary tree with 4n
leaves in this representation.
Mid Term Exams 3
✬ ✩
✫ ✪
4n
(1 point) If your goal is to minimize the area of the grid for a full binary tree with leaves,
explain which of the two representations you will choose (to relate both representations note
that 4n = 22n ). You do not need to solve the recurrences exactly; an asymptotic estimation is
enough.
✬ ✩
✫ ✪
Problem 2 (2 points)
Consider the following four pieces of code:
void f1 (int n) { void f2 (int n) {
int x = 2; int x = 2;
int y = 1; int y = 1;
while (y ≤ n) { while (y ≤ n) {
y = y + x; y = y + x;
x = x + 1; x = 2*x;
} } } }
int y = 1; int y = 1;
while (y ≤ n) { while (y ≤ n) {
y = y*x; y = y*x;
x = 2*x; x = x*x;
} } } }
✞ ☎
What is the cost of f 1? Answer: Θ( ✝
✞ ✆)
☎
What is the cost of f 2? Answer: Θ( ✝
✞ ✆)
☎
What is the cost of f 3? Answer: Θ( ✝
✞ ✆)
☎
What is the cost of f 4? Answer: Θ( ✝ ✆)
A correct answer without proper reasoning will not get any points.
✬
(0,5 points) Reasoning for f 1: ✩
✫ ✪
✬
(0,5 points) Reasoning for f 2: ✩
✫ ✪
(0,5 points) Reasoning for f 3:
Mid Term Exams 5
✬ ✩
✫ ✪
✬
(0,5 points) Reasoning for f 4: ✩
✫ ✪
Problem 3 (3 points)
(1.5 points) Let T [0 . . . n − 1] be a vector of integers. Show that if there is an inversion (i, j) in
T, then T has at least j − i inversions.
6 Mid Term Exams
✬ ✩
✫ ✪
(1.5 points) Let us fix a value N such that N ≥ 0 (that is, N is a constant in this exercise). By
using Divide & Conquer, implement in C++ a function
which, given an integer x and a vector of integers T of size n with at most N inversions,
determines if x is in T. The function should have worst-case cost Θ(log n). Show that indeed
it has this cost.
Hint: to solve question 2, use the fact from question 1. Besides, deal with subvectors of size
≤ 2N in the base case of the recursion, and with the rest of subvectors in the recursive case.
Mid Term Exams 7
✬ ✩
✫ ✪
Problem 4 (2 points)
✞ ☎
Four quickies:
✞
3. What is the recurrence for the cost of Strassen’s☎algorithm to multiply n × n matrices?
Answer T (n) = ✝ ✆.
4. An algorithm admits all 2n vectors of n bits as possible inputs. On 2n − 1 of these in-
puts the cost of the algorithm is Θ(n2 ), and on the remaining one the cost is Θ(n4 ).
Therefore, its worst-case cost is Θ(n4 ) and its best-case cost is Θ(n2 ). What is its
average-case cost when the input is chosen uniformly at random (so each input has
8 Mid Term Exams
probability 1/2n )? ✞ ☎
Answer: T (n) = Θ( ✝ ✆).
✫ ✪
Mid Term Exams 9
Problem 1 (2 points)
Hint: There are several ways to do it, one of them by proving O and Ω separately.
✬ ✩
✫ ✪
√
log n
(1 punt) Let f (n) = 2 and g(n) = n. Asymptotically, which one grows faster? Prove it.
10 Mid Term Exams
✬ ✩
✫ ✪
Problem 2 (3 points)
Consider the procedure mystery which takes as inputs a vector A and a positive integer k
such that all elements of A are between 0 and k, both included.
void mystery(const vector<int>& A, vector<int>& B, int k){
int n = A. size ();
vector<int> C(k+1, 0);
for (int j = 0; j < n; ++j) ++C[A[j]];
for (int i = 1; i ≤ k; ++i) C[i] += C[i−1];
B = vector<int>(n);
for (int j = n−1; j ≥ 0; −−j){
B[C[A[j]] − 1] = A[j ];
−−C[A[j]];
}
}
Mid Term Exams 11
(a) (1 point) What is the content of B at the end of the execution of mystery?
✬ ✩
✫ ✪
(b) (1 point) If n is the length of the vector A and you are guaranteed that k = O(n), what is
the asymptotic cost of mystery as a function of n?
✬ ✩
✫ ✪
(c) (1 point) Without writing any code, describe an algorithm for the following problem:
given a positive integer k, a vector A of n integers between 0 and k, both endpoints included,
and a vector P of m pairs of integers ( a0 , b0 ), . . . , ( am−1 , bm−1 ), with 0 ≤ ai ≤ bi ≤ k for each
i = 0, . . . , m − 1, you are asked to write the number of elements of A which are in the interval
[ai , bi ] for i = 0, . . . , m − 1 in time Θ(m + n + k), and in particular time Θ(m + n) when k =
O ( n ).
✬ ✩
✫ ✪
Problem 3 (3 points)
A board game of chance has 64 possible positions 1, . . . , 64. The rules of the game are such
that, from any position i ∈ {1, . . . , 64}, in one step a checker will hop to any other position
j ∈ {1, . . . , 64} with probability Pi,j . Let P = ( Pi,j )1≤i,j≤64 be this matrix of probabilities.
(a) (1 point) Remember that if R = P2 , then Ri,j = ∑64k=1 Pi,k Pk,j for each i, j. Taking into account
✤ ✜
that Pi,j is the probability of hopping from i to j in one step, how do you interpret Ri,j ?
✣ ✢
(b) (2 points) Design an algorithm that, given a matrix of probabilities P = ( Pi,j )1≤i,j≤64 and
given a certain number of steps t ≥ 0, computes the matrix ( Qi,j )1≤i,j≤64 where each Qi,j is
the probability that the checker, starting at position i, ends at position j after exactly t steps.
typedef vector<double> Row;
typedef vector<Row> Matrix;
✬ ✩
✫ ✪
Note 1: In order to get full grade your algorithm must run in Θ(log t) time.
Note 2: If you need any auxiliary function, implement on the back.
Note 3: Justify the cost of your algorithm on the back.
✬ ✩
✫ ✪
✬ ✩
✫ ✪
Mid Term Exams 15
Problem 4 (2 points)
(a) (1 point) Assume that an algorithm receives as input any of the 2n vectors of n bits with
equal probability. Assume that the worst-case cost of the algorithm is Θ(n2 ), and that its
best-case cost is Θ(n). How many inputs are required to cause cost Θ(n2 ) to be sure that the
average-case cost of the algorithm is Θ(n2 )?
✞ ☎
Answer: Ω( ✝ ✆)
✬
Justification: ✩
✫ ✪
(b) (0.5 points) Consider the following algorithm that adds one unit to a natural number that
comes represented by a vector vector<int> A of n decimal digits:
int i = n − 1;
while (i ≥ 0 and A[i] == 9) { A[i] = 0; −−i; }
if ( i ≥ 0) ++A[i]; else cout << ``Overflow' ' << endl;
If every digit A[i] of the input is equally likely and independent of the rest (that is, each
A[i] is one of the 10 possible digits with probability 1/10 independently of the other digits),
what is the probability that this algorithm makes exactly k iterations when 0 ≤ k ≤ n − 1?
✞ ☎
Answer: ✝ ✆
✬
Justification: ✩
✫ ✪
(c) (0.5 points) Use the master theorem for subtractive recurrences to solve the recurrencence
9
T (n) = 10 T (n − 1) + Θ(1) with base case T (0) = Θ(1).
✞ ☎
Answer: T (n) = Θ( ✝ ✆)
Justification:
16 Mid Term Exams
✬ ✩
✫ ✪
—————– END OF THE EXAM ——————-
(d) (optional extra bonus: 1 additional point to the grade) What does the recurrence T (n)
✬ ✩
from section (c) compute about the algorithm from section (b)?
✫ ✪
Mid Term Exams 17
The sieve of Eratostenes (276–194 BC) is a method to generate all prime numbers smaller
or equal than a given n. The method goes as follows: traversing the sequence of num-
bers 2, 3, 4, . . . , n, look for the next number x that is not yet marked, mark all its multiples
2x, 3x, 4x, . . . up to n, and repeat with the next x. When it finishes, those x ≥ 2 that are not
marked are the prime numbers. In C++:
For the first three questions below we ask for an exact (non-asymptotic) expression as a
function of n. If needed, use the notation ⌊z⌋ that rounds z to the maximum integer smaller
or equal than z; for example, ⌊π ⌋ = ⌊3.14 . . . ⌋ = 3.
✞ many times☎
(a) (0.33 points) How is M[y] = true executed when x is 2?
Answer: Exactly ✝ ✆ many times.
✞ many times ☎
(c) (0.33 points) How is M[y] = true executed when x is 17?
Answer: Exactly ✝ ✆ many times.
n
1
∑ p
= Θ(log log n).
p =2
p prime
Use this, in conjunction with the answers to the previous questions, to✞determine the cost☎of
the algorithm as a function of n, in asymptotic notation. Answer: Θ( ✝ ✆).
Justification:
18 Mid Term Exams
✬ ✩
✫ ✪
(e) (0.5 points) An improvement consists in replacing the condition x ≤ n in the external
loop by x*x ≤ n. Would this improve the asymptotic cost?
✬ and justification:
Answer ✩
✫ ✪
The school algorithm to multiply two n × n matrices makes Θ(n3 ) arithmetic operations. In
1969 Strassen found an algorithm that makes Θ(n2.81 ) arithmetic operations. Twenty one
years later, Coppersmith and Winograd discovered a method that makes Θ(n2.38 ) opera-
tions.
Assuming (for simplicity) that the implicit constants in the Θ notation are 1, 10 and 100,
respectively, and that they apply to every n ≥ 1 (that is, the costs are n3 , 10n2.81 and 100n2.38 ,
respectively, for every n ≥ 1), compute the least n for which one of these algorithms makes
less operations than another.
Mid Term Exams 19
✞ ☎
(a) (1 point) For n ≥ ✝ ✆, Strassen improves the school method.
✞ ☎
(b) (1 punt) For n ≥ ✝ ✆, Coppersmith-Winograd improves Strassen.
✬
Justifications: ✩
✫ ✪
(a) (1 point) Describe an algorithm that solves this problem. Explain the algorithm in words,
without writing code, but clearly enough so that the algorithm can be implemented. Assume
that the input is given by the vectors ( a1 , . . . , an ) and (b1 , . . . , bn ), with ai ≤ bi for every i =
1, . . . , n.
20 Mid Term Exams
✬ ✩
✫ ✪
(b) (1 point) Now, in addition to the sequence of n intervals, we are given a sequence m
different reals p1 , . . . , pm , and we want to determine how many fall in some interval of the
union (only the number is needed; not which ones). Using the algorithm from the previous
section, describe an algorithm that solves this problem in time O(n log n) when m = n. As-
sume that the input is given by the vectors a and b from the previous section, and the vector
( p1 , . . . , pm ) with pi 6= p j if i 6= j.
Mid Term Exams 21
✬ ✩
✫ ✪
(c) (1 punt) If you happened to know that m is bounded by a small constant independent
of n, say m ≤ 5, would you still use the same algorithm? If not, which one would you use
instead? If you choose a different algorithm, make its cost explicit.
✬ ✩
✫ ✪
✞ ☎
• (0,5 points) Determine if they are equal (=) or different (6=), and prove it:
✬ ✩
✫ ✪
• (0,5 points) Compute 21 · 22 · 23 · · · · · 299 · 2100 mod 9. This problem is not meant to be
solved with the help of a calculator.
✬ ✩
✫ ✪
• (1 point) Sort the functions that follow
√ increasingly according to their asymptotic
growth rates: n4 − 3n3 + 1, (ln(n))2 , n, n1/3 . Exceptionally, you are not required to
justify your answer.
✎ ☞
✍ ✌
✬ ✩
efficient?
✫ ✪
24 Mid Term Exams
Fibonacci numbers are defined by the recurrence f k = f k−1 + f k−2 for k ≥ 2, with f 0 = 0 and
f1 = 1. Answer the following exercises:
(a) (0.5 points) Consider the following function fib1 which, given a non-negative integer k,
returns f k :
Describe the asymptotic cost in time and space of fib1 (k) as a function of k as precisely as
possible.
✬ ✩
✫ ✪
(b) (1 point) Show that, for k ≥ 2, the following matrix identity holds:
k−1
1 1 fk f k−1
=
1 0 f k−1 f k−2
Mid Term Exams 25
✬ ✩
✫ ✪
(c) (1 point) Fill the gaps in the following code so that function fib2 (k) computes f k , given
a k ≥ 0.
✝ ✆
return C;
}
✞ ☎
else return ✝ ✆;
} }
✫ ✪
examines the n = v.size() positions of v and returns the first one that contains x, or −1 if
there is none.
Mid Term Exams 27
(a) (0.75 points) Describe as a function of n the asymptotic cost in time of position in the
best case as precisely as possible. When can this best case take place?
✬ ✩
✫ ✪
(b) (0.75 points) Describe as a function of n the asymptotic cost in time of position in the
worst case as precisely as possible. When can this worst case take place?
✬ ✩
✫ ✪
(c) (0.75 points) Show that for any integer n ≥ 1, the following identity holds:
n
i n 1
∑ 2i = 2 − 2n − 2n − 1 .
i=1
28 Mid Term Exams
✬ ✩
✫ ✪
(d) (1 point) Assume that we have a probability distribution over the input parameters.
Namely, the probability that x is element v[i ] is 2i1+1 for 0 ≤ i < n − 1, and that it is
element v[n − 1] is 2n1−1 . In particular, these probabilities add up 1, so that x is always
one of the n values of v.
Describe as a function of n the asymptotic cost in time of position in the average case as
precisely as possible.
Mid Term Exams 29
✬ ✩
✫ ✪
In this exercise we tackle the problem of, given two positive integers a and b, to compute
their greatest common divisor gcd( a, b). Recall that gcd( a, b) is, by definition, the only posi-
tive integer g such that:
1. g | a (g divides a),
2. g | b,
3. if d | a and d | b, then d | g.
(a) (1.25 points) Show that the following identities are true:
Hint: you can use that, given two positive integers a and b such that a > b, we have
gcd( a, b) = gcd( a − b, b).
✬ ✩
✫ ✪
(b) (1 point) Write a function int gcd(int a, int b) in C++ which, by using divide and
conquer and exercise (a), computes the greatest common divisor gcd( a, b) of two given
positive integer numbers a, b.
Hint: you can also use that for any positive integer a, gcd( a, a) = a.
Mid Term Exams 31
✬ ✩
✫ ✪
(c) (1 point) Assuming that a and b are positive integers, each of which represented with a
vector of n bits, describe the cost in time in the worst case of gcd(a , b) as a function of n
as precisely as possible. When can this worst case take place?
Assume that the cost of the following operations with integers of n bits: adding, sub-
tracting, comparing, multiplying/dividing by 2 is Θ(n), and that computing the remain-
der modulo 2 takes time Θ(1).
✬ ✩
✫ ✪
32 Mid Term Exams
Problem 1 (1 point)
Answer the following questions. In this exercise, you do not need to justify the answers.
✞
1. (0.2 points) The☎cost of Strassen’s algorithm for multiplying two matrices of size n × n
is Θ( ✝ ✆)
2. (0.6 points) The master theorem for subtractive recurrences states that given a recur-
rence T (n) = aT (n − c) + Θ(nk ) with a, c > 0 and k ≥ 0 then:
✞ ☎
✝
✞ ✆ if a < 1,
☎
✝
✞ ✆
☎
T (n) = if a = 1,
✝ ✆ if a > 1.
✞ ☎
3. (0.2 points) The mergesort sorting algorithm uses Θ( ✝ ✆) auxiliary space when
sorting a vector of size n.
Problem 2 (3 points)
In this problem costs are only considered in time. Consider the following program:
void h(int n) {
int p = 1;
for (int i = 1; i ≤ n; i++) {
f ( i );
if ( i == p) {
g(n );
p *= 2;
}} }
Justification:
Mid Term Exams 33
✬ ✩
✫ ✪
Justification:
34 Mid Term Exams
✬ ✩
✫ ✪
Problem 3 (3 points)
We say that a square matrix M of integer numbers of size n × n is symmetric if Mi,j = M j,i for
all i, j such that 0 ≤ i, j < n.
M0,0 M0,1 M0,2 ... M0,n−1
M1,0 M1,1 M1,2 ... M1,n−1
M2,0 M2,1 M2,2 ... M2,n−1
.. ..
. .
Mn−1,0 Mn−1,1 Mn−1,2 . . . Mn−1,n−1
w
w
w
M0,0 M1,0 M1,1 M2,0 M2,1 M2,2 . . . Mn−1,0 Mn−1,1 Mn−1,2 . . . Mn−1,n−1
1 2 0
2 −2 3
0 3 −1
1 2 −2 0 3 −1
(a) (0.5 points) Answer: the✞ ☎ of this representation for a symmetric matrix n × n
cost in space
as a function of n is Θ( ✝ ✆).
Justification:
✬ ✩
✫ ✪
(b) (1 point) Given n > 0 and a value k, the function
pair <int,int> row column(int n, int k );
j is the column of the coefficient pointed by k in a unidimensional vector that implements
a symmetric matrix n × n. If k is not a valid index, it returns (−1, −1). For example,
row column(3,2) returns (1, 1), row column(3,3) returns (2, 0), and row column(3,6) returns
(−1, −1).
✄
Complete the following implementation of row column:
int p(int x) { return ✂ ✁ ;}
✄
pair <int,int> row column(int n, int k) {
if (k < 0 or k ≥ p(n)) return ✂ ✁;
✄
int i = mystery(k, 0, n );
return {i , ✂ ✁ };
}
(c) (1 point) Analyse the cost in time in the worst case of the implementation of row column(int n, int k)
of the previous exercise as a function of n.
36 Mid Term Exams
✬ ✩
✫ ✪
functions double sqrt(double x) and int floor (double x) which
(d) (0.5 points) Using the √
respectively compute x and ⌊ x⌋ in time Θ(1), give an alternative implementation of
row column with cost Θ(1).
✬ ✩
✫ ✪
Problem 4 (3 points)
Assume that n is a power of 2, that is, of the form 2k for a certain k ≥ 0.
A square matrix A of real numbers of size n × n is a Monge matrix if for all i, j, k and l such
that 0 ≤ i < k < n and 0 ≤ j < l < n, it holds that
In other words, whenever we take two rows and two columns of a Monge matrix and con-
sider the four elements at the intersections of the rows and the columns, the sum of the
elements at the upper left and lower right corners is less than or equal to the sum of the
elements at the upper right and lower left corners. For example, the following matrix is a
Monge matrix:
10 17 13 28
16 22 16 29
24 28 22 34
11 13 6 6
(a) (1 point) Let f A (i ) be the index of the column where the the minimum element of the
i-th row appears (breaking ties if needed by taking the leftmost one). For example, in
the matrix above f A (0) = 0, f A (1) = 0, f A (2) = 2 i f A (3) = 2.
Mid Term Exams 37
✬ ✩
✫ ✪
(2) Recursively determine the column where the leftmost minimum appears for any
row of B1 and for any row of B2 .
(3) Find the column where the leftmost minimum appears for any row of A.
Explain how, by using the result of (2), one can accomplish (3) in time Θ(n).
38 Mid Term Exams
✬ ✩
✫ ✪
(c) (1 point) Compute the cost as a function of n of the algorithm proposed in the previous
exercise for computing the function f A for all rows of a Monge matrix A of size n × n.
Assume that step (1) can be carried out in time Θ(n).
✬ ✩
✫ ✪
Mid Term Exams 39
Problem 1 (2 points)
✞ ☎
(b) (0.2 pts.) The solution to the recurrence T (n) = 2T (n/4) + Θ(1) is ✝ ✆
✞ ☎
(c) (0.2 pts.) The solution to the recurrence T (n) = 2T (n/4) + Θ( n) is ✝ ✆
√
✞ ☎
(d) (0.2 pts.) The solution to the recurrence T (n) = 2T (n/4) + Θ(n) is ✝ ✆
(e) (0.3 pts.) What does Karatsuba’s algorithm compute? What is its cost?
✬ ✩
✫ ✪
(f) (0.3 pts.) What does Strassen’s algorithm compute? What is its cost?
✬ ✩
✫ ✪
40 Mid Term Exams
Problem 2 (3 points)
Given n ≥ 2, we say that a sequence of n integers a0 , . . . , an−1 is bi-increasing if an−1 < a0 and
there exists an index t (with 0 ≤ t < n) that satisfies the following conditions:
• a0 ≤ . . . ≤ a t − 1 ≤ a t
• a t +1 ≤ a t +2 ≤ . . . ≤ a n −1
For example, the sequence 12, 12, 15, 20, 1, 3, 3, 5, 9 is bi-increasing (take t = 3).
which, given a vector a that contains a bi-increasing sequence and an integer x, returns
whether x appears in the sequence or not. If you use auxiliary functions that are not part
of the C++ standard library, implement them too. The solution must have cost Θ(log(n))
in time in the worst case.
✬ ✩
✫ ✪
Mid Term Exams 41
(b) (1 pt.) Justify that the cost in time in the worst case of your function search is Θ(log(n)).
When does this worst case take place?
✬ ✩
✫ ✪
Problem 3 (2 points)
(a) (1 pt.) Given two integers m, n ≥ 0, what does mystery(m,n) compute? You do not need
to justify your answer.
✬ ✩
✫ ✪
(b) (1 pt.) Analyse the cost in time in the worst case as a function of n of mystery(m, n).
✬ ✩
✫ ✪
Problem 4 (3 points)
√
5+ 1
(a) (0.5 pts.) Let φ = 2 be the so-called golden number. Prove that φ−1 = φ − 1.
✬ ✩
✫ ✪
Mid Term Exams 43
✬ ✩
✫ ✪
44 Mid Term Exams
✫ ✪
Mid Term Exams 45
Problem 1 (2 points)
(a) (0.5 pts.) Compute the average cost of insertion sort to sort a vector with n different
log n
integers when with probability n one chooses a vector which is sorted backwards
log n
and with probability 1 − n one chooses a sorted vector.
✬ ✩
✫ ✪
bool mystery(int n) {
if (n ≤ 1) return false ;
if (n == 2) return true;
if (n%2 == 0) return false ;
for (int i = 3; i * i ≤ n; i += 2)
if (n%i == 0)
return false ;
return true;
}
✞ ☎
✞
Complete: function ☎ computes ✝
mystery ✆and
its cost is O( ✝ ✆). Do not justify the answer.
(c) (0.5 pts.) Show that n! = O(nn ) by applying the definition (not using limits).
46 Mid Term Exams
✬ ✩
✫ ✪
(d) (0.5 pts.) Show that n! = Ω(2n ) by applying the definition (not using limits).
✬ ✩
✫ ✪
Problem 2 (3 points)
For example, the sequence 1, 3, 5, 9, 4, 1 is unimodal, and its top is 9 (take t = 3).
(a) (1.5 pts.) Implement a function int top(const vector<int>& a) in C++ which, given a
non-empty vector a that contains a unimodal sequence, returns the index of the top of
the sequence. If you use auxiliary functions that do not belong to the C++ standard
library, implement them too. The solution must have cost Θ(log n) in time in the worst
case. Justify the cost is indeed Θ(log n) and give a situation in which this worst case
takes place.
Mid Term Exams 47
✬ ✩
✫ ✪
(b) (1.5 pts.) Implement a function bool search (const vector<int>& a, int x) in C++ which,
given a non-empty vector a that contains a unimodal sequence and an integer x, returns
whether x occurs in the sequence or not. If you use auxiliary functions that do not belong
to the C++ standard library, implement them too. The solution must have cost Θ(log n)
in time in the worst case. Justify the cost is indeed Θ(log n) and give a situation in which
this worst case takes place.
48 Mid Term Exams
✬ ✩
✫ ✪
Problem 3 (2 points)
The following class vect is a simplification of the class vector of the STL:
class vect {
int sz , * data , cap ;
int new capacity ();
void reserve (int new cap);
Mid Term Exams 49
public:
vect () { sz = cap = 0; data = nullptr ; }
int& operator[](int index) { return data [index ]; }
int size () { return sz ; }
void push back(int value ) {
if (sz ≥ cap) reserve (new capacity ());
data [sz] = value ;
++sz;
} };
Used space: sz = 4
data
In an object of class vect, field sz stores the number of el-
ements that the vector currently contains. The reserved 4 2 3 1
memory for the vector, pointed by field data, always has
enough space to store the sz current elements, and possi-
bly some more. The maximum number of elements that Reserved space: cap = 6
could be stored in the reserved memory is called capacity, and is the value of field cap.
The diagram on the right illustrates a possible implementation of a vector with contents
(4, 2, 3, 1). Note shaded cells are reserved but unused.
The reason for this data structure is that calling the system to ask for more memory is an ex-
pensive operation that one does not want to perform often. Function void reserve (int new cap),
whose implementation is not detailed here, takes care of that: it asks for a new memory frag-
ment that is big enough to store new cap elements, copies the contents of the old vector there
and updates conveniently the fields sz, data and cap.
Observe that every time function push back is called, if there is not enough reserved space,
function int new capacity () is called which, using the current capacity, determines the new
capacity for function reserve .
(a) (0.5 pts.) Consider the following implementation of function new capacity:
What is the exact value of cap in a vector that initially has cap = 0 and to which operation
reserve has been applied m times? Let us denote this value by C (m).
If we make n calls of push back over a vector which is initially empty (sz = cap = 0), how
many times exactly have we called reserve (in other words, which is the value of m such
that n ≤ C (m) and C (m − 1) < n)? Give also an asymptotic expression of this number
that is as precise and simple as possible.
50 Mid Term Exams
✬ ✩
✫ ✪
(b) (0.75 pts.) Show that the solution to the recurrence defined by C (0) = 0,
m
C (m + 1) = AC (m) + B, where A > 1 and B ≥ 1, is C (m) = BAA−−1 B for m ≥ 0.
✬ ✩
✫ ✪
(c) (0.75 pts.) The same as in exercise (a), but with the following function new capacity:
✫ ✪
Mid Term Exams 51
Problem 4 (3 points)
✫ ✪
(b) (0.5 pts.) What does the next function mystery do? Do not justify the answer.
52 Mid Term Exams
✖ ✕
(c) (1.5 pts.) Fill the gaps in the following alternative implementation of stable partition
and analyze its cost in time in the worst case. Assume that, in the worst case, at each
recursive call of stable partition rec we have that q − p = Θ(r − l + 1).
int stable partition (int x, vector<int>& a) {
return stable partition rec (x, a , 0, a . size ()−1);
}
int stable partition rec (int x, vector<int>& a, int l , int r) {
if ( l == r) {
✞ ☎
if (a[ l ] ≤ x) return l ;
else return ✝ ✆;
}
int m = ( l+r)/2;
int p = stable partition rec (x, a , l ✞
, m); ☎
✞
int q = stable ☎
partition rec (x, ✞a , ✝ ☎ ✆, r);
mystery(a✞, ✝ ☎ ✆, m, ✝ ✆);
return ✝ ✆; }
Analysis of the cost:
✬ ✩
✫ ✪
Mid Term Exams 53
Problem 1 (3 points)
Answer the following questions. You do not need to justify your answers.
(a) (0.5 pts.) The cost in time of the following code snippet as a function of n:
int j = 0;
int s = 0;
for (int i = 0; i < n; ++i)
if ( i == j * j ) {
for (int k = 0; k < n; ++k) ++s;
++j;
}
✞ ☎
is Θ( ✝ ✆).
examines the n = v.size() positions of v and returns the first one that contains x, or −1
if there is none.
Assume that✞x occurs☎in vector v. The asymptotic cost in time of position in the worst
case✞is Θ( ✝☎ ✆ ), and in the average case (assuming uniform probability) is
Θ( ✝ ✆).
✞
(c) (0.5 pts.) Give the order of magnitude of☎the following function in its simplest form:
5(log n) + 2 n + cos(n ) = Θ( ✝ ✆).
2
√ 8
1 if 0 ≤ n < 2
T (n) = 2
4 · T (n/2) + 3n + 2 log(log n) + 1, if n ≥ 2
✞ ☎
is T (n) = Θ( ✝ ✆).
54 Mid Term Exams
1 if 0 ≤ n < 2
T (n) =
4 · T (n − 2) + 3n2 + 2 log(log n) + 1, if n ≥ 2
✞ ☎
is T (n) = Θ( ✝ ✆).
Consider the following program, which reads a strictly positive integer m and a sequence of
n integers a0 , a1 , ..., an−1 that are guaranteed to be between 1 and m:
int main() {
int m;
cin >> m;
vector<int> a;
int x;
while (cin >> x)
a. push back(x );
(a) (0.5 pts.) Given y such that 0 ≤ y ≤ m, what is the value of b[y] at the end of main in
terms of the sequence a?
✬ ✩
✫ ✪
(b) (1 pt.) Let us define the median of the sequence a as the value p between 1 and m such
that b[ p] ≥ n2 and b[ p − 1] < n2 , where b is the vector computed as in the code above.
which, given n, the size of the sequence a, and b, computed as above, finds the median of
a. Solutions with cost Ω(m) will not be considered as valid answers. If you use auxiliary
functions, implement them too.
✬ ✩
✫ ✪
(c) (1 pt.) Analyze the cost of your function median of the previous exercise as a function of
m.
✬ ✩
✫ ✪
56 Mid Term Exams
Problem 3 (2 points)
for implementing complex numbers (with integer components), where real is the real part
and imag is the imaginary part of the complex number.
For example, if z is an object of type complex that represents the number 2 + 3i, then z . real =
2 and z. imag = 3.
✬ ✩
✫ ✪
Mid Term Exams 57
(b) (1 pt.) Justify that the cost in time of your function exp is Θ(log n).
✬ ✩
✫ ✪
(a) (1 pt.) Let us define the function U as U (m) = T (2m ). Using the recurrence for T, deduce
a recurrence for U.
58 Mid Term Exams
✬ ✩
✫ ✪
(b) (0.5 pts.) Solve asymptotically the recurrence for U of your answer to the previous exer-
cise.
✬ ✩
✫ ✪
✫ ✪
Mid Term Exams 59
2 n
(a) (0.5 pts.) Consider the functions f (n) = nn and g(n) = 22 .
✞ ☎
Which of the two functions grows asymptotically faster? ✝ ✆
Justification:
✬ ✩
✫ ✪
2 2 n n
Note: Read nn as n(n ) , and similarly 22 as 2(2 ) .
(b) (0.5 pts.) Assume that the inputs of size n of a certain algorithm are of the following
types:
• Type 1: for each input of this type, the algorithm takes time Θ(n4 ). Moreover, the
probability that the input is of this type is n13 .
• Type 2: for each input of this type, the algorithm takes time Θ(n3 ). Moreover, the
probability that the input is of this type is n1 .
• Type 3: for each input of this type, the algorithm takes time Θ(n). Moreover, the
probability that the input is of this type is 1 − n13 − n1 .
✞ ☎
Then the cost of the algorithm in the average case is ✝ ✆.
Justification:
60 Mid Term Exams
✬ ✩
✫ ✪
√
(c) (0.5 pts.) Solve the recurrence T (n) = 2T (n/4) + Θ( n).
✞ ☎
Answer: T (n) = Θ( ✝ ✆).
Justification:
✬ ✩
✫ ✪
Mid Term Exams 61
Problem 2 (2 points)
x0 if k = 0
x ( k) =
A · x ( k − 1) if k > 0
1 1 1 1
x0 = 2 and A = 1 0 0 ,
3 0 1 0
we have that
1 6 9
x ( 0) = 2 , x ( 1) = 1 , x ( 2) = 6 , ...
3 2 1
✫ ✪
62 Mid Term Exams
(b) (1 pt.) Explain at a high level how you would implement a function
vector<int> k th(const vector<vector<int>>& A, const vector<int>& x0, int k);
for computing the k-th term x(k) of the sequence defined by the matrix A and the vector
x0. Analyse also the cost in time as a function of k. The cost must be better than Θ(k).
✬ ✩
✫ ✪
Mid Term Exams 63
Given a natural number x, let us consider its representation in base 3. Assume that the
number of digits n in this representation is a power of 3. We split the sequence of digits in
three parts of the same size x2 , x1 and x0 , corresponding to the highest, middle and lowest
digits of x.
(b) (1 pt.) Let y be another natural number with n digits in its representation in base 3, and
let us define y2 , y1 and y0 analogously. Express x · y in terms of x2 , x1 , x0 , y2 , y1 and y0 .
No justification is needed.
✞ ☎
✝ ✆· 3
✞ ☎
x·y = 4n/3
+ ✝ ✆· 3
✞ ☎
3n/3
+ ✝ ✆· 3
✞ ☎
2n/3
+ ✝ ✆· 3
✞ ☎
n/3
+ ✝ ✆
(c) (1 pt.) Express x · y in terms of x2 , x1 , x0 , y2 , y1 and y0 in such a way that strictly less
than 9 products are introduced. No justification is needed.
✞ ☎
✝ ✆· 3
✞ ☎
x·y = 4n/3
+ ✝ ✆· 3
✞ ☎
3n/3
+ ✝ ✆· 3
✞ ☎
2n/3
+ ✝ ✆· 3
✞ ☎
n/3
+ ✝ ✆
(d) (1 pt.) Describe at a high level an algorithm for computing the product of two given
natural numbers represented in base 3 with a number of digits that is a power of 3.
Analyse the asymptotic cost in time.
64 Mid Term Exams
✬ ✩
✫ ✪
Problem 4 (3 points)
where b > 1 and k ≥ 0. Show that its solution is T (n) = Θ(logk+1 n).
Justification:
✬ ✩
✫ ✪
✞ ☎
bool search (const vector<int>& a, int x, int l , int r) {
if ( ✝ ✆) return x == a[l];
int m = ( l+r)/2;
auto beg = a .✞begin (); ☎
if (a[m] < ✝ ✆) ✞ ☎
return search (a , x, m+1, r) or binary search (beg + l , beg + ✝ ✆, x);
✞ ☎
else
return search (a , x, l , m) or binary search (beg + ✝ ✆, beg + r + 1, x);
}
66 Mid Term Exams
✞ ☎
bool search (const vector<int>& a, int x) { return search (a , x, 0, ✝ ✆); }
Note: Given an element x and iterators first, last such that the interval [first, last) is
sorted (increasingly or decreasingly), the function binary search(first, last, x) returns true
if x appears in the interval [first, last) and false otherwise, in logarithmic time in the size
of the interval in the worst case.
(c) (1 pt.) Analyse the cost in time in the worst case of a call search (a , x), where a is a vector
of size n > 0 that contains a unimodal sequence and x is an integer. Describe a situation
in which this worst case can take place.
✬ ✩
✫ ✪
Mid Term Exams 67
Problem 1 (2 points)
For each of the following statements, mark with an X the corresponding cell depending on
whether it is true or false.
Note: Each right answer will add 0.2 points; each wrong answer will subtract 0.2 points,
except in the case that there are more wrong answers than right ones, in which the grade of
the exercise will be 0.
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10)
TRUE
FALSE
Problem 2 (3 points)
Given two matrices of Booleans A and B of size n × n, we define their logical product P = A · B
as the n × n matrix which at the coefficient of the i-th row and j-th column (0 ≤ i, j < n)
contains:
−1
n_
pij = ( aik ∧ bkj )
k=0
(a) (0.5 pts.) Consider the following function for computing the logical product:
68 Mid Term Exams
✞ ☎
What is the cost in time in the worst case in terms of n? The cost is Θ( ✝ ✆).
✚ ✙
(b) (1 pt.) Consider the following alternative for computing the logical product:
✚ ✙
✞ ☎
What is the cost in time in the worst case in terms of n? The cost is Θ( ✝ ✆).
✛ ✘
✚ ✙
(c) (1.5 pt.) Explain at a high level how to implement a function for computing the logical
product of matrices that is more efficient asymptotically in the worst case than those
proposed at sections (a) and (b). What is its cost in time in the worst case?
✬ ✩
✫ ✪
Problem 3 (2 points)
int mystery(int n) {
return mystery rec (n, 0, n+1);
}
(a) (1 pt.) Given an integer n ≥ 0, what does function mystery compute?
✬ ✩
✫ ✪
✞ ☎
(b) (1 pt.) What is the cost in time of mystery(n) in terms of n? The cost is Θ( ✝ ✆)
✫ ✪
Problem 4 (3 points)
Consider the problem of, given a vector of integers (possibly with repetitions), sorting it in
increasing order. The following costs are in time and are asked in terms of n, the size of the
vector.
(a) (0.25✞pts.) What is the
☎ cost of the insertion sort algorithm in the best case? The cost is
Θ( ✝ ✆).
Mid Term Exams 71
(b) (0.25✞pts.) What is the☎cost of the insertion sort algorithm in the worst case? The cost is
Θ( ✝ ✆).
(e) (0.75 pts.) Fill the gaps of the function my sort defined below, so that given a vector of
integers v, it sorts it increasingly:
void my sort(vector<int>& v) {
int n = v. size ();
double lim = n * log (n );
int c = 0;
for (int i = 1; i < n; ++i) {
int x = v[ i ];
✞ ☎
int j ;
; j > 0 and ✝ ☎
for ( j = i ✞ ✆; −−j) {
v[ j ] = ✝ ✆;
++c;
✞ ☎
}
v[ j ] = ✝ ✆;
if (c > lim) {
merge sort (v );
return;
}
}
}
The auxiliary function merge sort is an implementation of the mergesort algorithm, and
function log computes the neperian logarithm (that is, in base e).
✞ ☎
(f) (1.25 pts.) What is the cost of my sort in the best case? The cost is Θ( ✝ ✆).
✞ ☎
What is the cost of my sort in the worst case? The cost is Θ( ✝ ✆).
Justify your answers and give one example of best case and one of worst case.
72 Mid Term Exams
✬ ✩
✫ ✪
2
Lab Exams
74 Lab Exams
Shift 1
Problem 1
Jutge.org, Problem P39846: Treasures in a map (4)
(https://www.jutge.org/problems/P39846_en).
Problem 2
Jutge.org, Problem P71701: Peaceful kings
(https://www.jutge.org/problems/P71701_en).
Shift 2
Problem 1
Jutge.org, Problem P84415: Bag of words
(https://www.jutge.org/problems/P84415_en).
Problem 2
Jutge.org, Problem P22295: The travelling tortoise
(https://www.jutge.org/problems/P22295_en).
Problem 1
Jutge.org, Problem P69865: Picking up coins
(https://www.jutge.org/problems/P69865_en).
Problem 2
Jutge.org, Problem P98123: Filling the bag
(https://www.jutge.org/problems/P98123_en).
Problem 1
Jutge.org, Problem P90766: Treasures in a map (3)
(https://www.jutge.org/problems/P90766_en).
Lab Exams 75
Problem 2
Jutge.org, Problem P67329: DNA
(https://www.jutge.org/problems/P67329_en).
Problem 1
Jutge.org, Problem P47386: Gossip
(https://www.jutge.org/problems/P47386_en).
Problem 2
Jutge.org, Problem P87462: Pacman
(https://www.jutge.org/problems/P87462_en).
Problem 1
Jutge.org, Problem P90861: Queues of a supermarket (1)
(https://www.jutge.org/problems/P90861_en).
Problem 2
Jutge.org, Problem P14952: Topological sort
(https://www.jutge.org/problems/P14952_en).
Problem 1
Jutge.org, Problem X07174: Nombres sense prefixos prohibits
(https://www.jutge.org/problems/X07174_ca).
Problem 2
Jutge.org, Problema X34032: El cavall afamat
(https://www.jutge.org/problems/X34032_en).
76 Lab Exams
Problem 1
Jutge.org, Problem P60796: Treasures in a map (2)
(https://www.jutge.org/problems/P60796_en).
Problem 2
Jutge.org, Problem X21319: Circuit Value Problem
(https://www.jutge.org/problems/X21319_en).
Problem 1
Jutge.org, Problem P81453: Shortest path
(https://www.jutge.org/problems/P81453_en).
Problem 2
Jutge.org, Problem P89318: Forbidden words
(https://www.jutge.org/problems/P89318_en).
Problem 1
Jutge.org, Problem X41530: Forest
(https://www.jutge.org/problems/X41530_en).
Problem 2
Jutge.org, Problem X92609: Two coins of each kind (3)
(https://www.jutge.org/problems/X92609_en).
Problem 1
Jutge.org, Problem P86108: LOL
(https://www.jutge.org/problems/P86108_ca).
Lab Exams 77
Problem 2
Jutge.org, Problem P27258: Monstres en un mapa
(https://www.jutge.org/problems/P27258_ca).
Problem 1
Jutge.org, Problem P43164: Treasures in a map (5)
(https://www.jutge.org/problems/P43164_en).
Problem 2
Jutge.org, Problem P31389: Rooks inside a rectangle
(https://www.jutge.org/problems/P31389_en).
Problem 1
Jutge.org, Problem P12887: Minimum spanning trees
(https://www.jutge.org/problems/P12887_en).
Problem 2
Jutge.org, Problem P54070: Rightmost position of insertion
(https://www.jutge.org/problems/P54070_en).
Shift 1
Problem 1
Jutge.org, Problem P76807: Sudoku
(https://www.jutge.org/problems/P76807_en).
Problem 2
Jutge.org, Problem P99753: Bi-increasing vector
(https://www.jutge.org/problems/P99753_en).
78 Lab Exams
Shift 2
Problem 1
Jutge.org, Problem P18679: Balance beam (1)
(https://www.jutge.org/problems/P18679_en).
Problem 2
Jutge.org, Problem P74219: Fibonacci numbers (2)
(https://www.jutge.org/problems/P74219_en).
Problem 1
Jutge.org, Problem P49889: Consonants and vowels (1)
(https://www.jutge.org/problems/P49889_en).
Problem 2
Jutge.org, Problem P96413: Erdos number (2)
(https://www.jutge.org/problems/P96413_en).
Problem 1
Jutge.org, Problem P70756: Partitions
(https://www.jutge.org/problems/P70756_en).
Problem 2
Jutge.org, Problem P71496: Cuts
(https://www.jutge.org/problems/P71496_en).
Problem 1
Jutge.org, Problem P29033: Two colors
(https://www.jutge.org/problems/P29033_en).
Problem 2
Jutge.org, Problem X39049: Powers of permutations
(https://www.jutge.org/problems/X39049_en).
Lab Exams 79
Problem 1
Jutge.org, Problem X82938: Search in a unimodal vector
(https://www.jutge.org/problems/X82938_en).
Problem 2
Jutge.org, Problem X19647: Cheapest Routes
(https://www.jutge.org/problems/X19647_en).
3
Final Exams
82 Final Exams
✞ ☎
1. Let f (n) = n log(cos(nπ ) + 4)). Then f (n) = Θ( ✝ ✆).
✞ ☎
2. Which is the last digit of 71024 written in decimal notation? Answer: ✝ ✆.
✞
3. What is the recurrence for the cost of Strassen’s☎algorithm to multiply n × n matrices?
Answer T (n) = ✝ ✆.
4. An algorithm admits all 2n vectors of n bits as possible inputs. On 2n − 1 of these in-
puts the cost of the algorithm is Θ(n2 ), and on the remaining one the cost is Θ(n4 ).
Therefore, its worst-case cost is Θ(n4 ) and its best-case cost is Θ(n2 ). What is its
average-case cost when the input is chosen uniformly at random (so each input has
probability 1/2n )? ✞ ☎
Answer: T (n) = Θ( ✝ ✆).
✫ ✪
(a) (1.0 points) Implement a C++ function bst redo (const vector<Elem> &v) that recon-
structs a binary search tree from its preorder traversal v. For example, on input v = [2 1 7 3 8],
the function should produce the following tree:
2
1 7
3 8
You may assume that v is the correct preorder of some BST. If you need so, you may imple-
ment an auxiliary function.
✬ ✩
✫ ✪
84 Final Exams
(b) (1.0 points) Implement a C++ function bst build AVL(const vector<Elem> &v) that re-
constructs a BST that satisfies the AVL property from a sorted vector of elements v. If you
need so, you may implement an auxiliary function.
✬ ✩
✫ ✪
(c) (1.0 points) If we add a field n. height to denote the height of node n in the BST where
it sits (with leaves at height 0 and therefore NULLs would be at height −1), complete the
following code so that the result indicates if the BST T is an AVL:
bool is AVL(bst T) {
if (T == NULL) return true;
else if (T−>lc == NULL or T−>rc == NULL) return (T−>height ≤ 1);
✬ ✩
else {
✫ ✪
} }
Final Exams 85
A tournament graph is a directed graph in which there is exactly one arc between every pair
of different vertices, and that does not have any arc from any vertex to itself.
a) (0.5 points) Write a C++ function that tells whether a given graph with n vertices is a
tournament graph in Θ(n2 ) time in the worst case.
bool is tournament(const Graph& G) {
✬ ✩
✫ ✪
}
b) (1.0 points) Prove, by induction on the number of vertices, that every tournament graph
has a Hamiltonian path, that is, a path that visits every vertex exactly once (hint: show that
a new vertex can be inserted in a path of n − 1 vertices to get a path of n vertices).
✬ ✩
✫ ✪
c) (1.0 points) Using the previous proof, give an algorithm that returns a Hamiltonian path
of a tournament graph (clarity will be more valued than efficiency):
86 Final Exams
✫ ✪
}
✫ ✪
Final Exams 87
DHAM: Given a directed graph, determine whether there is a cycle that visits all
vertices exactly once.
The problem of Hamiltonian cycles in undirected graphs UHAM is the same, but where the
input graph is undirected. Steffy knowns that DHAM can be reduced to UHAM by simply
applying the following transformation to each of the vertices v of the directed graph:
IN MID OUT
v v v v
Roy and Johnny say that vertex vMID is not actually needed: they say connecting vIN — vOUT
and ignoring vMID is enough. But Steffy replies: “Guys, take a look at this input to DHAM
and then we talk again”:
e c
a
d b
What did Steffy mean? Is she right? (be concise but precise, please)
✬ ✩
✫ ✪
88 Final Exams
Recall (from the practical work of the competència transversal) that Bellman-Ford algorithm
allows one to find minimum-weight paths in a weighted directed graph, even when weights
are negative.
✞ cost of Bellman-Ford
(a) (0.5 points) Which is the worst-case ☎ algorithm on a graph with |V |
vertices and | E| edges? Answer: Θ( ✝ ✆)
(b) (0.5 points) Steffy says that the statement at the beginning of this exercise cannot be
completely right, since otherwise one could efficiently find a Hamiltonian cycle in a directed
graph G = (V, E) by simply assigning weight −1 to each edge in G, choosing any vertex
s, and applying Bellman-Ford to check if the minimum-weight path from s to one of the
vertices that have an edge towards s has weight −(|V | − 1). How can you explain this
paradox? (or have we proved that P = NP?)
✬ ✩
✫ ✪
Final Exams 89
Hint: There are several ways to do it, and one of them is to consider the O and the Ω
separately.
✬ ✩
✫ ✪
√
log n
(1 point) Let f (n) = 2 and g(n) = n. Which one is asymptotically faster? Prove it.
90 Final Exams
✬ ✩
✫ ✪
With the usual representation of binary search trees (this also holds for AVLs), some algo-
rithms may be inefficient. For instance, function smaller (T, x) that given a tree T and a key
x, returns the number of elements in T that have a key ≤ x.
allows, between others, an implementation of smaller (T, x) with cost Θ(h), where h is the
height of T (which would be Θ(log n) on average for a random BST and Θ(log n) in the
worst case for an AVL, where n is the size of T).
✬ ✩
int smaller ( bst T, const Key& x)
✫ ✪
✬ ✩
✫ ✪
A mate of your is preparing the EDA lab exam and gets stuck in a problem in the “Graph
Algorithms” list of the Judge. After a bit of thought, she realizes that this problem essen-
tially asks to determine whether an undirected graph represented with adjacency lists is
2-colorable. That is, is it is possible to assign a red or blue color to each vertex so that no two
adjacent vertices are painted with the same color?
Unfortunately, the Judge responds Time Limit Exceeded to all her submissions! At this mo-
ment, your mate decides to look for some more efficient code in the Internet and finds the
following implementation in a web forum:
bool two col aux(const vector<vector<int>>& g, int u, vector<bool>& col,
vector<bool>& marked, bool is red) {
col [u] = is red ;
marked[u] = true;
for (int i = 0; i < g[u]. size (); ++i) {
Final Exams 93
int v = g[u][ i ];
if (not marked[v]) {
if (not two col aux (g, v, col , marked, not is red )) return false ;
}
}
return true;
}
Now, she expects that the code will be efficient enough, since after a bit of analysis, she
knows it takes O(|V | + | E|) time. After sending it to the Judge, the verdict is... Wrong Answer!
(2 points) Write a correct version of two col aux so that two colorable () properly determines
if a graph is 2-colorable within O(|V | + | E|) time.
✬ ✩
✫ ✪
(1 point) Thanks to your help (hopefully!), your mate could fix the code and get it accepted.
Irritated, she continues reading the forum. The author of the code affirms there that his
program can be easily extended to solve the 3-colorability problem with the same asymptotic
complexity. Do you believe him? Why or why not?
✬ ✩
✫ ✪
Given a directed graph whose arcs have costs that can be negative, we wish to determine if
it contains one or more negative cost cycles (just if they exist, not how many there are, nor
Final Exams 95
(0,5 points) Give the proper name of a famous algorithm that helps solving this problem
with just a little adaptation.
✎ ☞
✍ ✌
(0,5 points) Briefly explain (but with enough details to implement it) how this algorithm
works.
✬ ✩
✫ ✪
(0,5 points) What is the cost of this algorithm? Express it using the number of vertices |V |
and the number of arcs | E| in the input graph.
✎ ☞
✍ ✌
(0,5 point) Explain how to adapt the general algorithm to our particular problem (negative
96 Final Exams
cycle detection).
✬ ✩
✫ ✪
Final Exams 97
One from the midterm, one from that thing, and one more (2 points)
✞ ☎
(1 point) Determine if they are equal (=) or different (6=), and prove it:
✫ ✪
(0.5 points) What is the algorithm from the competencia transversal useful for? Choose only
one (reasoning not requested):
• To compute the most likely philogenetic tree.
• To compute the optimal price of a long option over a finantial product.
• To fit all 9 Beethoven symphonies into a single CD.
• To solve recurrences that do not match the form of the master theorems.
(0.5 points) The S UBSET S UM problem is the following: Given a list of natural numbers
a1 , . . . , am and a target b, all written in decimal notation, determine if there exists a subset
S ⊆ {1, . . . , m} such that ∑i∈S ai = b. If d is the number of digits of the largest natural number
in the input, indicate which is the only correct assertion (reasoning not requested):
• The problem is NP-complete and, therefore, there does not exist any algorithm of cost
O(m · d · 10d ) unless P = NP.
• The problem is NP-complete and, therefore, there does not exist any algorithm of cost
polynomial in m and d unless P = NP.
98 Final Exams
• The problem is NP-complete but nonetheless a known algorithm exists whose cost is
polynomial in both m and d.
• The problem can be solved in time O(d · m · log m), and hence cost polynomial in the
size of the input, as follows: first, all m numbers are added to a max-heap; then, the
numbers are extracted one by one until either the sum exceeds b, or all numbers are
extracted without reaching b, or the sum of the extracted numbers is exactly b.
Pointers (2 points)
Given two binary trees, create a new binary tree that is their intersection (and leave the given
trees untouched). For example:
1
0
0
1 1
0
0
1 1
0
0
1
1
0
0
1 1
0
0
1 1
0
0
1 1
0
0
1
0
1
0
1 0
1
0 1
1 0
0
1 0
1
0 1
1 0
0
1 0
1
0
1
1
0
0
1 1
0
0
1 1
0
0
1
1
0
0
1 1
0
0
1 1
0
0
1 1
0
0
1 1
0
0
1 1
0
0
1
0
1
0 1
1 0
0
1 0
1
0
1 0
1
0
1 0
1
0
1
1
0
0
1 1
0
0
1 1
0
0
1 1
0
0
1 1
0
0
1 1
0
0
1
(1.5 points) Using the type and header as given, solve this problem.
✬ ✩
✫ ✪
}
(0.5 points) What is its cost, in the worst case, as a function of the sizes n1 and n2 of t1 and
t2?
✬ ✩
✫ ✪
Onions is a logical puzzle1 in which we are given a square matrix n × n divided into n
regions, each region painted with a different color.
1 The original puzzle is called Alberi (tree in Italian) and the apps (both iOS and Android) for this game were
fill in the gaps in the C++ code below for the corresponding backtracking algorithm to find
one solution, or determining that no solution exists. If there is more than one solution, any
solution is good.
class Onions {
int n;
bool solution found ;
OnionBoard board; // current partial solution
vector<int> col; // col[i] = column of the onion at row i
vector<bool> onion in col; // onion in col[i] = there is an onion in column i
vector<bool> onion in region; // onion in region[i] = there is an onion in region i
public:
Onions(const OnionBoard& initial board) {
board = initial board ;
n = board . size ();
col = vector<int>(n);
onion in col = vector<bool>(n, false);
onion in region = vector<bool>(n, false);
solution found = false ;
backtrack (0);
Final Exams 101
✫ ✪
✬
backtrack (k+1); ✩
✫ ✪
}} }
// returns true iff the partial solution board has an onion in a cell adjacent to (i,j);
// you are not asked to implement it
bool onion in neighborhood (int i , int j );
Tweets (4 points)
A social network of the Twitter type has different users. These maintain a ‘follow’ relation-
ship with other users (for instance, Salvador follows Anna, Ivet and Leo Messi, but Leo
Messi does not follow anyone). Users can add or remove other users from their list of fol-
lowed users. Moreover, at any moment, a user can tweet a message. Also, at any time, a
user can obtain the k most recent tweets of the users she follows. (That is, if she follows n
users, she gets at most k tweets, not nk).
Users are represented by a User struct that contains its personal data (including a string with
its name that identifies it in a unique way) and that tweets are represented with a struct
Tweet that contains the message and its posting time:
struct User {
... // personal data
string name; // different users have different names
102 Final Exams
};
struct Tweet {
string message; // body of the message
int post time ; // number of miliseconds since some epoch
};
Explain which data structures and algorithms you would use to store the described in-
formation and to implement the following operations in the most efficient way: adding
and removing follow relationships, tweeting a message, and obtaining the k most recent
tweets from the users that are followed by a given user. Do not explain how users are creat-
ed/deleted. Analyse the cost of your operations.
The expected answer is open but be specific defining the SocialNetwork data structure and
describe (without code) how to implement the following operations:
// Returns a list with the k most recent tweets of the users followed by u; user exists.
list <Tweet> k most recent tweets (const SocialNetwork& sn, string u, int k );
Final Exams 103
✬ ✩
✫ ✪
104 Final Exams
Problem 1 (3 pts.)
Consider a probability distribution over the input parameters such that the probability
that x is element v[i ] is n1 for 0 ≤ i < n.
✞ ☎
Answer: the average-case cost in time of position as a function of n is Θ( ✝ ✆).
Justification:
✬ ✩
✫ ✪
(c) (1 pt.) What does Floyd-Warshall’s algorithm compute? What is its cost in time and
space in the worst case? (no justification is needed)
✬ ✩
✫ ✪
Problem 2 (2 pts.)
set <int> S;
for (int i = 0; i < n; ++i) {
S. insert (V[i ]);
106 Final Exams
(a) (0.4 pts.) What does the code snippet write if n = 6 and the elements of V are 42 100 23
12 20 24 (in this order)?
✤ ✜
✣ ✢
(b) (0.4 pts.) Give a high-level explanation on which values are written by the code snippet
with an arbitrary V with n different integers.
✬ ✩
✫ ✪
(c) (0.4 pts.) Justify what is the asymptotic cost in time of the code snippet in the worst case
as a function of n.
Hint: You can use Stirling’s formula: log(n!) = Θ(n log n).
✬ ✩
✫ ✪
(d) (0.4 pts.) If the elements of V were repeated, could the code snippet compute something
different from what was answered in exercise (b)? If the answer is yes, show an example.
If the answer is no, explain why.
Final Exams 107
✬ ✩
✫ ✪
(e) (0.4 pts.) Write with full detail an alternative program to the given code snippet that
computes the same for an arbitrary vector V with n different integers (n ≥ 1), but with
asymptotic cost in time strictly less than that computed in exercise (c). Justify what is
this asymptotic cost.
✬ ✩
✫ ✪
Problem 3 (2 pts.)
Consider the problem of, given a directed acyclic graph G = (V, E), generating all its topo-
logical orderings. The next program solves it (assume V = {0, 1, ..., n − 1}):
108 Final Exams
#include <iostream>
#include <vector>
using namespace std;
However, it is too slow. Rewrite function top sorts to solve the problem more efficiently,
without changing main. Implement also the auxiliary functions that you use, except for
print solution and the functions of the standard C++ library.
Final Exams 109
✬ ✩
✫ ✪
Problem 4 (3 pts.)
Let G be the adjacency matrix of a directed graph with n vertices. The closure matrix of (the
graph represented by) G, which we will represent with G ∗ , is an n × n matrix defined as
follows: given u, v such that 0 ≤ u, v < n, the coefficient in row u and column v is
∗ 1 if there is a (possibly empty) path from u to v in the graph
Guv =
0 otherwise
110 Final Exams
where the vertices of the graph are identified with the integers from 0 to n − 1 as usual.
which, given the adjacency matrix G of a directed graph, returns its closure. Analyze
the asymptotic cost in time in the worst case.
✬ ✩
✫ ✪
(b) (1 pt.) Let us denote by I the n × n identity matrix, that is, the matrix where all coeffi-
cients are 0 except for those in the diagonal, which are 1. Show that, for any k ≥ 0, there
is a path in the graph from u to v with at most k edges if and only if the coefficient in
row u column v of the matrix ( I + G )k (the matrix resulting from multiplying k matrices
I + G) is different from 0, i.e., ( I + G )kuv 6= 0.
Final Exams 111
✬ ✩
✫ ✪
(c) (1 pt.) Give a high-level description of an algorithm for, given the adjacency matrix of a
directed graph G, computing its closure G ∗ in time strictly better than Θ(n3 ) in the worst
case. Give the cost in the worst case and justify it. Assume that the cost of arithmetic
operations with integers is constant.
Hint: if there is a path from u to v, there is at least one with at most n − 1 edges.
✬ ✩
✫ ✪
112 Final Exams
(a) (0.9 pt.) The master theorem for dividing recurrences claims that if we have a recurrence
of the form T (n) = aT (n/b) + Θ(nk ) with a > 0, b > 1 and k ≥ 0, then, letting α = logb a,
✞ ☎
✝
✞ ✆
☎
if α < k,
T (n) = ✝
✞ ✆
☎
if α = k,
✝ ✆ if α > k.
(b) (0.3 pt.) The smallest k such that the following statement is true:
(c) (0.3 pt.) Class stack <T> of STL has two member functions top:
On the other hand, class priority queue <T> has one function top only:
What is the problem with class priority queue <T> having a function T& top()?
✬ ✩
✫ ✪
Final Exams 113
Wrong answers penalize with the same grade as right ones reward.
✞ ☎
(a) The following binary tree is a red-black tree (answer Yes or No): ✝ ✆
3 9
✞ ☎
(b) The following binary tree is a red-black tree (answer Yes or No): ✝ ✆
3 9
1 6 NULL NULL
✞ ☎
(c) The following binary tree is a red-black tree (answer Yes or No): ✝ ✆
1 7
NULL NULL
5 9
3 6 NULL NULL
✞ ☎
(d) The following binary tree is a red-black tree (answer Yes or No): ✝ ✆
114 Final Exams
3 8
NULL NULL
2 4
✞ ☎
(e) The following binary tree is a red-black tree (answer Yes or No): ✝ ✆
2 8
NULL
1 5 9
3 6 NULL NULL
NULL NULL
✞ ☎
(f) The following binary tree is a red-black tree (answer Yes or No): ✝ ✆
3 8
2 4 NULL NULL
Problem 3 (2 pts.)
returns a position between l and r, both included, in which x appears in v (or −1 if there is
none):
(a) (0.75 pt.) According to the value of the parameter s, give a recurrence that describes the
cost in time in the worst case of position as a function of n = r −l+1.
✬ ✩
✫ ✪
(b) (0.5 pt.) According to the value of s, when does that worst case take place?
✬ ✩
✫ ✪
(c) (0.75 pt.) According to the value of s, solve the recurrence of the answer of exercise (a)
and give the asymptotic cost in the worst case.
116 Final Exams
✬ ✩
✫ ✪
Problem 4 (2 pts.)
void push front (const T& x); void push back (const T& x);
void pop front (); void pop back ();
respectively. Also, one can recover the element at the beginning with the functions:
(a) (1 pt.) A weighted directed graph G = (V, E) is binary if for any edge e ∈ E, its weight is
0 or 1. By using a deque, implement in C++ a function
that, given a binary graph G and two vertices x and y of G, returns the minimum cost of
going from x to y (or −1 if it is not possible to go from x to y).
Assume vertices are represented with integers between 0 and n − 1, where n is the num-
ber of vertices; and that the graph is represented with adjacency lists with a vector<vector<pair<int,int>>
where the first component of the pair s represents the successor vertex and the second
one, the weight of the edge.
✬ ✩
✫ ✪
(b) (0.5 pt.) Analyze the cost in time of your function minimum cost in the worst case as a
function of the number of vertices |V | and edges | E|.
118 Final Exams
✬ ✩
✫ ✪
(c) (0.5 pt.) Which cost in time in the worst case would minimum cost have if we used the
version of Dijkstra’s algorithm that implements the priority queue with a binary heap
(like the ones seen at class)?
✬ ✩
✫ ✪
Problem 5 (3 pts.)
The problem of DISEQUALITIES consists in, given an interval of integers and a set of dise-
qualities (6=) between variables, to determine whether there is a solution to all disequalities
with values in the interval. More formally, given:
• a (finite) interval [l, u] ⊂ Z,
• a set of variables V, and
• a set D of disequalities of the form x 6= y, where x, y ∈ V,
we have to determine where there is s : V → Z such that:
• for any x ∈ V we have s( x) ∈ [l, u], and
• for any x 6= y ∈ D it holds s( x) 6= s(y).
Final Exams 119
We will consider that the set of variables is of the form V = { x0 , x1 , . . . , xn−1 } for a cer-
tain n > 0, and will identify the variables with integers between 0 and n − 1. Besides,
we will represent the inputs for the problem of DISEQUALITIES by means of the type
inp DISEQUALITIES defined as follows:
struct inp DISEQUALITIES {
int l , u, n;
set <pair<int,int>> D; // each pair (i, j) is a disequality xi 6= x j
};
(a) (1 pt.) Complete the following implementation of the function
bool has solution (const inp DISEQUALITIES& e);
that solves the problem of DISEQUALITIES:
✫ ✪
(c) (0.75 pt.) Consider the problem of COLORING: given an undirected graph G and a
natural number c > 0, to determine whether one can paint the vertices of G with c colors
in such a way that any edge has the endpoints painted with different colors.
120 Final Exams
Suppose that we represent the inputs for the problem of COLORING with the type
inp COLORING defined as follows:
struct inp COLORING {
vector<vector<int>> G; // graph represented with adjacency lists
int c ;
};
Implement a polynomial reduction from COLORING to DISEQUALITIES:
inp DISEQUALITIES reduction(const inp COLORING& ec);
✬ ✩
✫ ✪
(d) (0.5 pt.) Do you see feasible to find a polynomial algorithm for DISEQUALITIES? Why?
✤ ✜
✣ ✢
Final Exams 121
Problem 1 (2 pts.)
✞ ☎
(a) (0.25 pts.) A graph with n vertices has O( ✝ ✆) edges.
✞ ☎
(b) (0.25 pts.) A connected graph with n vertices has Ω( ✝ ✆) edges.
✞ ☎
(c) (0.25 pts.) A complete graph with n vertices has Ω( ✝ ✆) edges.
✞ ☎
(d) (0.25 pts.) A min-heap with n vertices has Θ( ✝ ✆) leaves.
✞ ☎
(e) (0.25 pts.) A binary search tree with n vertices has height Ω( ✝ ✆).
✞ ☎
(f) (0.25 pts.) A binary search tree with n vertices has height O( ✝ ✆).
✞ ☎
(g) (0.25 pts.) An AVL tree with n vertices has height Ω( ✝ ✆).
✞ ☎
(h) (0.25 pts.) An AVL tree with n vertices has height O( ✝ ✆).
Problem 2 (3 pts.)
Let G = (V, E) be a directed graph with weights ω : E → R. We want to solve the problem
of, given a vertex s ∈ V, to compute the distance from s to all vertices of the graph.
Recall that:
• a path is a sequence of vertices that are connected consecutively by arcs; that is to say,
(u0 , u1 , . . . , uk ) such that for all 1 ≤ i ≤ k, we have (ui−1 , ui ) ∈ E.
• the weight of a path is the sum of the weights of its arcs:
k
ω ( u0 , u1 , . . . , u k ) = ∑ ω ( u i−1 , u i ) .
i=1
• the distance of a vertex u to a vertex v is the weight of the path (called minimum path)
with minimum weight among those leaving from u and arriving at v, if it exists.
(a) (0.2 pts.) Let us assume that for any edge e ∈ E, we have ω (e) = 1; that is to say, all
weights are 1. Which algorithm can we use to solve efficiently the problem of the dis-
tances?
☛ ✟
✡ ✠
122 Final Exams
(b) (0.2 pts.) Let us assume that for any edge e ∈ E, we have ω (e) ≥ 0; that is to say, all
weights are non-negative. Which algorithm can we use to solve efficiently the problem
of the distances?
☛ ✟
✡ ✠
(c) (0.2 pts.) Which algorithm can we use to solve efficiently the problem of the distances,
if some weights can be negative?
☛ ✟
✡ ✠
(d) (0.4 pts.) Which condition over the cycles of the graph must be satisfied so that, for all
pairs of vertices u, v ∈ V, there exists a minimum path from u to v?
✬ ✩
✫ ✪
(e) (1 pt.) A function π : V → R is a potential of the graph if it satisfies that, for any edge
(u, v) ∈ E, we have π (u) − π (v) ≤ ω (u, v). Moreover, the reduced weights ωπ are defined
as ωπ (u, v) = ω (u, v) − π (u) + π (v) for any (u, v) ∈ E.
Prove that if c is a path from u to v then ωπ (c) = ω (c) − π (u) + π (v).
✬ ✩
✫ ✪
Final Exams 123
(f) (1 pt.) Suppose that the graph has a potential π. Then, it can be proved that for all pairs
of vertices u, v ∈ V there is a minimum path with weights ω from u to v. Assuming this
fact, explain how to use the potential π to compute the distance from a given vertex
s to all vertices of the graph with an alternative algorithm to that of part (c) when the
weights can be negative.
✬ ✩
✫ ✪
Problem 3 (2 pts.)
We define a type matrix to represent square matrices of real numbers. Consider the following
program:
typedef vector<vector<double>> matrix;
(a) (0.5 pts.) What does the function matrix mystery(const matrix& M) compute in terms of
the matrix M?
✤ ✜
✣ ✢
(b) (0.5 pts.) If M is an n × n matrix, what is the cost in the worst case of the function
matrix mystery(const matrix& M) as a function of n? Justify your answer.
✬ ✩
✫ ✪
(c) (1 pt.) Implement in C++ a function that computes the same as the function matrix mystery(const matrix&
and which takes Θ(n3 log n) time in the worst case. Also implement the auxiliary func-
tions you use, except for aux and the functions of the standard library of C++. Justify
that the cost of your function is as required.
Final Exams 125
✬ ✩
✫ ✪
Problem 4 (3 pts.)
The problem of HAMILTONIAN GRAPH consists in, given an (undirected) graph, to decide
whether it is Hamiltonian, that is to say, whether there exists a cycle that visits all its vertices
exactly once. It is well-known that HAMILTONIAN GRAPH is an NP-complete problem.
126 Final Exams
It is also known that, from the proof that a problem belongs to class NP, one can derive a
brute force algorithm that solves it. The following function bool ham(const vector<vector<int>>& G)
which, given a graph G represented with adjacency lists, returns if G is Hamiltonian, imple-
ments this algorithm in the case of HAMILTONIAN GRAPH.
1 bool ham rec(const vector<vector<int>>& G, int k, vector<int>& p) {
2 int n = G. size ();
3 if (k == n) {
4 vector<bool> mkd(n, false);
5 for (int u : p) {
6 if (mkd[u]) return false ;
7 mkd[u] = true;
8 }
9 for (int k = 0; k < n; ++k) {
10 int u = p[k ];
11 int v;
12 if (k < n−1) v = p[k+1];
13 else v = p [0];
14 if ( find (G[u].begin (), G[u].end (), v) == G[u].end()) return false ;
15 }
16 return true;
17 }
18 for (int v = 0; v < n; ++v) {
19 p[k] = v;
20 if (ham rec(G, k+1, p)) return true;
21 }
22 return false ;
23 }
24
returns an iterator to the first element in the range [first, last) that compares equal to val. If
no such element exists, the function returns last.
(a) (0.5 pts.) Identify the variable in the previous program which represents the witness
when the function ham returns true.
✞ ☎
✝ ✆
(b) (0.5 pts.) Identify the code corresponding to the verifier in the previous program. To
that end, use the line numbers on the left margin.
✞ ☎
✝ ✆
Final Exams 127
(c) (1 pt.) Fill the following gaps so that the function ham2 computes the same as the func-
tion ham, but more efficiently.
bool ham2 rec(const vector<vector<int>>& G, int k, int u, vector<int>& next) {
int n✞= G. size
☎
();
if ( ✝ ✆ == n) ✞ ☎
return find (G[u].begin (), G[u].end (), ✝ ✆) 6= G[u].end();
✞ ☎
for (int v : G[u])
✞ ✝ ☎ ✆
if (next[v] == ){
next[u] = ✝ ✆;
if (ham2 rec(G, k+1, v, next )) return true;
next[u] = −1;
}
return false ;
}
✤ ✜
ple, increasingly). Explain how to use this to make the function of part (c) more efficient.
✣ ✢
(e) (0.5 pts.) Suppose that G is a disconnected graph. Explain how to use this to make the
✗ ✔
function of part (c) more efficient.
✖ ✕
128 Final Exams
Problem 1 (2 pts.)
84
52 79
36 45 73 71
18 12 13
draw the max-heap resulting from adding 55 and deleting the maximum element (in
this order). You do not need to justify anything.
✬ ✩
✫ ✪
✫ ✪
int m1 = i+p;
int m2 = m1+p;
return f (v, i , m1) + f (v, m1+1, m2) + f(v, m2+1, j );
}
✬ ✩
✫ ✪
✬ ✩
✫ ✪
130 Final Exams
Problem 2 (2 pts.)
Given a vector A with n different integers and another vector B with m different integers,
we want to compute a vector (of different integers) which is the intersection of the two (that
is, that contains the common elements).
For example, if A = (3, 1, 6, 0) and B = (4, 6, 1, 2, 7), then any of the two vectors (1, 6), (6, 1)
would be a valid answer.
Let us assume that A and B are not necessarily sorted. Give a high-level description of how
you would implement a function
vector<int> intersection (const vector<int>& A, const vector<int>& B);
that returns the intersection of A and B with a cost in time of O(n + m) in the average case.
Justify the cost.
✬ ✩
✫ ✪
Final Exams 131
Problem 3 (3 pts.)
Given a directed acyclic graph (DAG) G, the level of its vertices is defined inductively as
follows:
• if v is a root of G (a vertex without predecessors) then level(v) = 0
• otherwise,
(a) (0.9 pts.) Fill out the following table pointing out, for each vertex of the given DAG, its
level. What is the depth of the DAG? You do not need to justify anything.
C
B D
A E
G
H
F
A B C D E F G H
level : depth :
(b) (0.4 pts.) For each of the following statements, mark with an X the corresponding cell
depending on whether it is true or false. You do not need to justify anything.
Note: Every right answer will add 0.1 points; every wrong answer will subtract 0.1
points, except when there are more wrong answers than right ones, in which case the
grade of the exercise will be 0.
(1) For any vertex u of a DAG G, if u is a leaf (vertex without successors) then level(u) =
depth( G ).
(2) For any vertex u of a DAG G, if level(u) = depth( G ) then u is a leaf.
(3) The depth of a DAG with n vertices is O(n).
(4) The depth of a DAG with n vertices is Ω(log n).
(1) (2) (3) (4)
TRUE
FALSE
(c) (1.7 pts.) Here it is assumed that graphs are represented with adjacency lists, and that
vertices are identified with consecutive natural numbers 0, 1, etc.
Fill the gaps of the following function:
vector<int> levels(const vector<vector<int>>& G);
132 Final Exams
which, given a DAG G = (V, E), returns a vector that, for each vertex u ∈ V, contains the
value level(u) in position u. Give and justify the cost in time in the worst case in terms
of n = |V | and m = | E|.
queue<int> Q;
for (int u = 0; u < n; ++u)
if (pred[u] == 0) {
✞ ☎
Q.push(u);
✝ ✆
}
✝ ✆
if (pred[v] == 0) Q.push(v);
} }
return lvl ;
}
Cost and justification:
✬ ✩
✫ ✪
Problem 4 (3 pts.)
Given n > 0, a derangement (of size n) is a permutation of {0, . . . , n − 1} without fixed points;
that is, π is a derangement if and only if π (i ) 6= i for all i, 0 ≤ i < n. For example π = (2, 0, 3, 1)
Final Exams 133
Fill out the following C++ code for generating all derangements of size n. You do not need
to justify anything.
✞ ☎
void generate (int k , int n, vector<int>& p, vector<bool>& used) {
if ( ✝ ✆) write(p, n);
else {
for (int✞ i = 0; i < n; ++i) ☎
( ✝
if ✞ ☎✆
){
✝
✞ ✆
☎
✝ ✆
✞ ☎
generate (k+1, n, p, used );
✝ ✆
}
}
};
In this exercise, by heaps we mean min-heaps of integer numbers. We will also assume their
usual implementation, in which a complete binary tree with n elements is represented with
a vector of size n + 1 whose first component (the one with index 0) is not used.
(a) (1.25 pts.) Let v be a vector of size n + 1 that represents a complete binary tree with n
integers. Moreover, except possibly for a certain node with index i (where 1 ≤ i ≤ n),
it meets the min-heap property: if a node has a value x and one of its descendants has
value y, then x ≤ y.
Implement in C++ the function
void shift down (vector<int>& v, int i );
which sinks the node with index i until the min-heap property is restored for all nodes.
✬ ✩
✫ ✪
assigns the value x to the node with index i (discarding the previous value in the node)
and updates v so that it still represents a heap.
You can use the function shift down of the previous exercise, as well as the following
function shift up :
void shift up (vector<int>& v, int i) {
if ( i 6= 1 and v[i/2] > v[i ]) {
swap(v[i ], v[ i /2]);
shift up (v, i /2);
} }
✬ ✩
✫ ✪
Problem 2 (2 pts.)
Given a permutation π of {1, . . . , n}, the value π (i ) is a left maximum if π (i ) > π ( j) for all j,
1 ≤ j < i. The first element π (1) is always a left maximum.
For example π = (3, 1, 5, 4, 6, 2) has 3 left maxima (namely, π (1) = 3, π (3) = 5 and π (5) = 6).
Fill the gaps in the following C++ code that writes the permutations of {1, . . . , n} that have
exactly k left maxima, where 1 ≤ k ≤ n.
int n, k ;
vector<int> perm;
vector<bool> used;
void write () {
cout << perm[1];
136 Final Exams
✞
void generate (int i , int lm,☎int mx) { ✞ ☎
✝
if ( ✞ ✆ > k or ✝ ☎ ✆ < k ) return;
if ( ✝ ✆) write();
else {
✞ ☎
for (int j = 1; j ≤ n; ++j)
if ( ✝
✞ ☎✆
){
✝ ✞ ☎ ✆
✞
perm[i] = ✝ ✆; ☎
if ( ✝ ✆) generate(i+1, lm+1, j);
✞ ☎
else generate ( i+1, lm, mx);
✝ ✆
}
}
}
int main() {
cin >> n >> k;
perm = vector<int>(n+1);
used = vector<bool>(n+1, false);
generate (1, 0, 0);
}
Problem 3 (3 pts.)
✣ ✢
Final Exams 137
If one wanted to use function mystery as a hash function for the type string, would 0 be
an adequate value for x? Why?
✬ ✩
✫ ✪
(b) (1 pt.) For each of the following statements, mark with an X its cell depending on
whether it is true or false. You do not need to justify anything.
Note: Each right answer will add 0.25 points; each wrong answer will subtract 0.25
points, except for the case when there are more wrong answers than right ones, in which
the grade of the exercise will be 0.
Recall: SAT is the problem of, given a propositional formula, to decide whether it is
satisfiable or not; and HAM is the problem of, given a graph, to decide whether it is
hamiltonian.
(1) If there exists an NP problem that belongs to P then P = NP.
(2) If there is a polynomial reduction from a problem X to SAT then there is a polyno-
mial reduction from X a HAM.
(3) There are problems of the class NP for which there is no known algorithm that solves
them.
(4) If a problem X can be reduced polynomially to a problem Y ∈ P then X ∈ P.
(1) (2) (3) (4)
TRUE
FALSE
(c) (0.5 pts.) Consider the following forest of rooted trees, which represents a collection of
disjoint sets:
0 5
1 2 6 7 8
3 4 9 10
✞ ☎
11
(d) (0.5 pts.) Consider the following variant of binary search, which given:
• an element x,
138 Final Exams
✫ ✪
Given two digraphs G1 = (V, E1 ) and G2 = (V, E2 ) defined over the same set of vertices V,
the composition of G1 and G2 is the digraph denoted by G1 ◦ G2 whose vertices are V, and
whose edges are the following set:
Note: In this exercise it is allowed that digraphs have auto-cycles, that is, edges of the form
(u, u).
2 2
1 3 1 3
0 0
6 6
5 4 5 4
G1 G2
Final Exams 139
Draw G1 ◦ G2 .
✬ ✩
✫ ✪
(b) (1 pt.) Assume that G1 and G2 are represented with adjacency matrices. Implement in
C++ a function
which, given the adjacency matrices of G1 and of G2 , computes the adjacency matrix of
G1 ◦ G2 in time Θ(|V |3 ) in the worst case. Justify that the cost is as required.
140 Final Exams
✬ ✩
✫ ✪
(c) (1 pt.) Explain how to implement function comp in time better than Θ(|V |3 ).
✬ ✩
✫ ✪
Final Exams 141
Problem 1 (2 pts.)
(a) (0.5 pts.) Class stack <T> of STL has two member functions top:
On the other hand, class priority queue <T> has one function top only:
What is the problem with class priority queue <T> having a function T& top()?
✬ ✩
✫ ✪
(b) (0.5 pts.) For the alphabet { A, B, C, D } and the following table of absolute frequencies
for 100 characters, give a Huffman code and draw its tree. You do not need to justify
anything.
A 70
B 10
C 15
D 5
✬ ✩
✫ ✪
(c) (0.5 pts.) Draw the AVL tree resulting from inserting the three keys x, y, z in this order
to the AVL tree of the figure. Note that the keys are ordered in alphabetic order. You do
not need to justify anything.
142 Final Exams
f s
c j r v
a d i m q u
✬ ✩
✫ ✪
84
52 79
36 45 73 71
18 12 13
draw the max-heap resulting from adding 55 and deleting the maximum element (in
this order). You do not need to justify anything.
Final Exams 143
✬ ✩
✫ ✪
Problem 2 (3 points)
where b > 1 and k ≥ 0. Show that its solution is T (n) = Θ(logk+1 n).
Justification:
✬ ✩
✫ ✪
element at is called the top of the sequence. For example, the sequence 1, 3, 5, 9, 4, 1 is
unimodal, and its top is 9 (take t = 3).
given a non-empty vector a that contains a unimodal sequence and an integer x, returns
whether x appears in the sequence or not. No justification is needed.
✞ ☎
bool search (const vector<int>& a, int x, int l , int r) {
if ( ✝ ✆) return x == a[l];
int m = ( l+r)/2;
auto beg = a .✞begin (); ☎
if (a[m] < ✝ ✆) ✞ ☎
return search (a , x, m+1, r) or binary search (beg + l , beg + ✝ ✆, x);
✞ ☎
else
return search (a , x, l , m) or binary search (beg + ✝ ✆, beg + r + 1, x);
}
✞ ☎
bool search (const vector<int>& a, int x) { return search (a , x, 0, ✝ ✆); }
Note: Given an element x and iterators first, last such that the interval [first, last) is
sorted (increasingly or decreasingly), the function binary search(first, last, x) returns true
if x appears in the interval [first, last) and false otherwise, in logarithmic time in the size
of the interval in the worst case.
(c) (1 pt.) Analyse the cost in time in the worst case of a call search (a , x), where a is a vector
of size n > 0 that contains a unimodal sequence and x is an integer. Describe a situation
in which this worst case can take place.
Final Exams 145
✬ ✩
✫ ✪
Problem 3 (3 pts.)
A student of EDA is preparing for the lab exam and gets stuck in a problem of the list
“Graph Algorithms” of the Judge. After thinking for a while, he realizes that he must,
essentially, given a graph (undirected, represented with adjacency lists), determine whether
it is 2-colorable; that is, whether it is possible to assign a color red or blue to each vertex of
the graph, so that adjacent vertices are not painted with the same color.
Unfortunately, the Judge returns a Time Limit Exceeded verdict to all his submissions. At
this point the student decides to look in the Internet for a more efficient code, and finds the
following one in a forum:
bool two col aux(const vector<vector<int>>& g, int u, vector<bool>& col,
vector<bool>& marked, bool is red) {
col [u] = is red ;
marked[u] = true;
for (int v : g[u]) {
if (not marked[v]) {
if (not two col aux (g, v, col , marked, not is red )) return false ;
}
}
146 Final Exams
return true;
}
Now he expects that this code will be efficient enough, since after a bit of analysis he con-
cludes that it takes time O(|V | + | E|). He submits it to the Judge, and it turns out that...
Wrong Answer!
(a) (2 pts.) Write a correct version of two col aux so that two colorable determines whether
a graph is 2-colorable in time O(|V | + | E|).
✬ ✩
vector<bool>& marked, bool is red)
✫ ✪
Final Exams 147
(b) (1 pt.) Finally the student finds a way to fix the code and the Judge accepts it. Uneasy,
he carries on reading the forum. The author of the wrong code claims that his program
can be easily extended to the problem of 3-colorability with the same asymptotic cost.
Do you believe it? Why?
✬ ✩
✫ ✪
Problem 4 (2 pts.)
Consider the following problem: given n positive integer numbers a0 , a1 , ..., an−1 and two
other integers l and u such that 0 ≤ l ≤ u ≤ ∑in=−01 ai , we have to find all possibles solutions
( x0 , x1 , . . . , xn−1 ) ∈ {0, 1}n to the double inequation:
l ≤ a0 x0 + a1 x1 + · · · + a n − 1 x n − 1 ≤ u
(a) (1 pt.) Complete the following program to solve the previous problem:
int n, l , u;
vector<int> a;
vector<bool> x;
int main() {
cin >> n >> l >> u;
a = vector<int>(n);
for (int i = 0; i < n; ++i) cin >> a[i ];
int s = 0;
for (int i = 0; i < n; ++i) s += a[i ];
x = vector<bool>(n);
148 Final Exams
✞ ☎ ✞ ☎ ✞ ☎
sols ( ✝ ✆, ✝ ✆, ✝ ✆);
}
(b) (1 pt.) The program in the previous exercise writes the solutions in increasing lexico-
graphic ordering. For example, for the input n = 3, l = 3, u = 5 and ai = i + 1 (0 ≤ i ≤ 2),
the output is:
001
011
101
110
Explain how to change function sols to write all solutions in decreasing lexicographic
ordering, that is, in the reverse order of the previous example, without using additional
space. In particular, the algorithm consisting in storing all the output in a vector, and at
✬ ✩
the end sort it and write it will not be considered as a valid answer.
✫ ✪
Final Exams 149
50
25 70
12 35 65 86
10 30 40
✬ ✩
✫ ✪
(b) (0.75 pts.) Draw the heap resulting from removing the maximum from the following
max-heap:
84
52 29
36 45 23 21
18 12 13
✬ ✩
✫ ✪
✞ ☎
(c) (0.5 pts.) The solution to the recurrence T (n) = 3T (n/9) + Θ(n) is ✝ ✆
150 Final Exams
✞ ☎
(d) (0.5 pts.) The solution to the recurrence T (n) = 3T (n/9) + Θ( n) is ✝ ✆
√
✞ ☎
(e) (0.5 pts.) The solution to the recurrence T (n) = 3T (n/9) + Θ(1) is ✝ ✆
(f) (0.5 pts.) Consider the following flow network with origin s and destination t, and the
indicated flow:
3; 4
v1 v3
4; 4 3; 3
1; 3 0; 2
s t
0; 6 1; 1
v2 v4
1; 3
For each arc, we indicate the flow along the arc and its capacity, separated by a semi
colon. E.g., the arc from v1 to v3 carries 3 units of flow and has capacity 4.
Draw the residual network of this network with respect to the given flow.
✬ ✩
✫ ✪
Problem 2 (4 pts.)
In this exercise we will work with a type polynomial for representing polynomials in a vari-
able x with integer coefficients.
Final Exams 151
(a) (0.5 pts.) Suppose that we implement polynomials with vectors of integers (that is,
polynomial is vector<int>), so that for k = 0, 1, . . . the k-th value of the vector is the coef-
ficient of xk . Hence, for example the vector {1, 0, −3} represents the polynomial 1 − 3x2 .
Given a polynomial p and integers c 6= 0 and k ≥ 0, consider the following function:
Answer: ✞ ☎
the function mystery computes ✝ ✞ ☎ ✆
and its cost in time in terms of n = p. size () and k is Θ ✝ ✆.
(b) (1.5 pts.) Suppose that now we implement polynomials with a dictionary with integer
keys and integer values, so that a pair of the dictionary with key k and value v (with
v 6= 0) represents the monomial v · xk . So for example the dictionary with pairs key-
value {(0, 1), (2, −3)} represents the polynomial 1 − 3x2 .
More specifically, let us assume that polynomial is unordered map<int,int>.
Fill the gaps in the following reimplementation of the function mystery that uses this
new representation of polynomials.
Give and justify an accurate upper bound of the cost in time in the average case.
✬ ✩
✫ ✪
152 Final Exams
(c) (0.25 pts.) From this section onwards we will suppose again that we implement polyno-
mials with vectors of integers (that is, polynomial is vector<int>).
Consider the following function, which defines the operator + for polynomials for writ-
ing in C++ the sum of two polynomials p and q as p + q:
Answer: ✞ ☎
the cost of the function in terms of n is Θ( ✝ ✆).
(d) (1.75 pts.) Fill the gaps in the following function, which defines the operator ∗ for poly-
nomials for writing in C++ the product of two polynomials p and q as p ∗ q. You can use
the functions that appear in the previous sections. Suppose that p.size() = q.size() = n,
where n ≥ 1 is a power of 2. The cost of the function must be strictly better than Θ(n2 ).
polynomial p0 q0 = p0 * q0;
polynomial p1 q1 = p1 * q1;
Final Exams 153
✬ ✩
✫ ✪
}
✫ ✪
Given a natural N ≥ 1, we consider the set of the first N naturals {0, . . . , N − 1}. A set cover
of {0, . . . , N − 1} is a collection of subsets S0 , ..., S M−1 of {0, . . . , N − 1} such that each of the
S −1
first N naturals is included in at least one of the subsets, that is, iM =0 Si = {0, . . . , N − 1}.
For example, suppose that N = 4, S1 = {0, 1, 3}, S2 = {0, 3} and S3 = {0, 2, 3}. Then if K = 2
the answer is TRUE (since S1 ∪ S3 = {0, 1, 2, 3}), but if K = 1 the answer is FALSE (since there
is no single Si that covers the set {0, 1, 2, 3}).
154 Final Exams
This implementation has a serious efficiency bug. Explain what is this error and rewrite
the previous code with the required changes to fix it.
Final Exams 155
✬ ✩
✫ ✪
(b) (1 pt.) Given a graph G = (V, E), a vertex cover is a subset of vertices W ⊆ V such that
every edge {u, v} ∈ E has at least one of the two endpoints in W, that is, u ∈ W or v ∈ W.
The problem of VERTEX-COVER consists in, given a natural K and a graph G = (V, E),
156 Final Exams
to determine whether there exists a subset W ⊆ V with at most K vertices that is a vertex
cover of G.
✫ ✪
Incorrect reduction and counterexample:
Final Exams 157
✬ ✩
✫ ✪
(c) (0.75 pts.) Suppose we have been able to reduce VERTEX-COVER to SET-COVER, and
that we know that VERTEX-COVER is NP-complete. Can we deduce only from this
that SET-COVER is an NP-complete problem? If so, justify it. Otherwise show that
SET-COVER is NP-complete (assuming that VERTEX-COVER reduces to SET-COVER
and that VERTEX-COVER is NP-complete).
✬ ✩
✫ ✪
4
Solutions to Mid Term Exams
160 Solutions to Mid Term Exams
(a) Θ(nlog 7 )
(b) The master theorem for subtractive recurrences states that given a recurrence T (n) =
aT (n − c) + Θ(nk ) with a, c > 0 and k ≥ 0 then
k
Θ( n )
if a < 1,
T ( n ) = Θ( n k+1 ) if a = 1,
n
Θ( a c ) if a > 1.
(c) Θ(n)
(a) The cost of the program is determined by the sum of the costs of two groups of instruc-
tions:
A. The instructions that are executed at each iteration of the loop: the evaluation of
the condition i ≤n, the call f ( i ), the evaluation of the condition i == p and the
increment i++.
B. The instructions that are executed when the condition of the if is true: the call g(n)
and the increment p *= 2.
We count separately the contribution to the total cost of the two groups of instructions:
A. If the cost of f (m) is Θ(m), then at the i-th iteration the cost of A is Θ(i ). So in total
the contribution to the cost is ∑ni=1 Θ(i ) = Θ(∑ ni=1 i ) = Θ(n2 ).
B. If the cost of g(m) is Θ(m), then every time that the condition of the if is true the
cost of B is Θ(n). Since this happens Θ(log n) times, the contribution to the total
cost is Θ(n log n).
Hence in total the cost of h(n) is Θ(n2 ) + Θ(n log n) = Θ(n2 ).
(b) Let us consider the same two groups of instructions of the previous exercise, and again
we count separately their contribution to the total cost:
A. If the cost of f (m) is Θ(1), then the cost of A at each iteration is Θ(1). Since Θ(n)
are performed, the cost in total is Θ(n).
B. If the cost of g(m) is Θ(m2 ), then every time that the condition of the if is true the
cost of B is Θ(n2 ). Since this happens Θ(log n) times, the cost is Θ(n2 log n).
Hence in total the cost of h(n) is Θ(n) + Θ(n2 log n) = Θ(n2 log n).
Solutions to Mid Term Exams 161
(a) The i-th row uses i + 1 cells (0 ≤ i < n). In total, the consumed space is
n −1 n
∑ ( i + 1) = ∑ j = Θ ( n 2 ) .
i=0 j=1
(c) Let C ( N ) be the cost in the worst case of a call to the function mystery(k, l , r), where
N = r − l + 1. The recurrence that describes C ( N ) is
C ( N ) = C ( N/2) + Θ(1),
since one makes one recursive call over an interval of half the size, and operations that
take constant time. By using the master theorem of divisive recurrences, the solution to
the recurrence is C ( N ) = Θ(log N ).
Therefore, the cost in the worst case of a call to function row column(n, k) is Θ(log n).
(d) The index i of the searched row is the natural number 0 ≤ i < n such that p(i ) ≤ k <
p(i + 1). We can compute it by solving the second degree equation p( x) = k and taking
i = ⌊ x ⌋:
(a) Let us show it by contradiction. Let us assume that i is such that 0 ≤ i < n − 1 i f A (i +
1) < f A (i ). Let us take k = i + 1, j = f A (i + 1) and l = f A (i ), so that 0 ≤ i < k < n and
0 ≤ j < l < n. Since j = f A (k), we have that Ak,j ≤ Ak,l . And as l = f A (i ), we have
that Ai,l ≤ Ai,j ; in fact, since j < l, it must be Ai,l < Ai,j . Thus, by adding we have that
Ai,l + Ak,j < Ai,j + Ak,l . This contradicts that A is a Monge matrix.
(b) For each even i, one can compute the column where the leftmost minimum of the i-th
row of A appears as follows. From the recursive call over B1 , we have the column j1
where the leftmost minimum of the i-th row of A appears between columns 0 and n2 − 1.
Similarly, from the recursive call over B2 , we have the column j2 where the leftmost
minimum of the i-th row of A appears between columns n2 and n − 1. Hence, f A (i ) = j1
if Ai,j1 ≤ Ai,j2 , and f A (i ) = j2 otherwise.
For each odd i, one determines f A (i ) by examining the columns between f A (i − 1) and
f A (i + 1) (defining f A (n) = n − 1 for notational convenience), and choosing the index
where the leftmost minimum appears. This has cost Θ( f A (i + 1) − f A (i − 1) + 1). In
total:
n −1
n
∑ Θ( f A (i + 1) − f A (i − 1) + 1) = Θ((n − 1) − f A (0) +
2
) = Θ( n )
i=1,i odd
(c) Let C (n) be the cost of the proposed algorithm for computing the function f A for all
rows of a Monge matrix A of size n × n.
Apart from the two recursive calls in step (2) over matrices of size n2 × n2 , steps (1) and
(3) require time Θ(n) in total. So the recurrence that describes the cost is
By using the master theorem of divisive recurrences, the solution to the recurrence is
C (n) = Θ(n log n).
Solutions to Mid Term Exams 163
(a) It computes mn .
(b) The cost of the function is determined by the cost of the loop. Each iteration requires
time Θ(1), since only arithmetic operations and integer assignments are performed.
Therefore, the cost is proportional to the number of iterations. We observe that if y is
even, then y is reduced to half its value. And if y is odd with y > 1, then at the next
iteration the value y − 1 is considered, which is even, and then it is reduced to half its
value. Hence if n ≥ 1 the number of iterations is between 1 + ⌊log(n)⌋ and 1 + 2⌊log(n)⌋.
Altogether, the cost is Θ(log(n)).
Hence φ−1 = φ − 1.
φn − (−φ)−n
1−1
F (n) = √ = √ = 0.
5
n =0 5
φn − (−φ)−n
= √
5
(a) Insertion sort has cost Θ(n) when the vector is already sorted, and cost Θ(n2 ) when it is
sorted backwards. So the average cost is:
log n log n
(1 − ) Θ( n ) + Θ(n2 ) = Θ(n − log n + n log n) = Θ(n log n)
n n
Let C (n) be the cost in time in the worst case of function top rec on a vector of size n. In
the worst case (for example, when the top is in one of the ends of the vector) a recursive
call will be made on a subvector of size n/2, in addition to operations of constant cost
(arithmetic computations, comparisons and assignments of integers, vector accesses). So
we have the recurrence C (n) = C (n/2) + Θ(1), which by the master theorem of divisive
recurrences has solution C (n) = Θ(log n).
(b) A possible solution that uses the function int top (const vector<int>& a) of the previous
exercise and the function binary search of STL:
Solutions to Mid Term Exams 167
In another possible solution, the previous search function can be replaced by:
When function search searches in a vector of size n, in addition to calling function top,
one or two binary searches are made, each of which has cost O(log n), and also oper-
ations of constant cost. So the cost of search is O(log n) + O(log n) + O(1) = O(log n).
Moreover, if for example the top of the sequence is in one of the ends of the vector,
then the cost is Θ(log n) + O(log n) + O(1) = Θ(log n). So the cost in the worst case is
Θ(log n).
(a) After m calls to function reserve on an initially empty vector, the capacity of the vector
is of C (m) = Am elements. So the number of calls to reserve after n calls to push back is
the least m such that Am ≥ n, that is, ⌈ An ⌉. Since A is constant, m is Θ(n).
(b) By induction.
168 Solutions to Mid Term Exams
BA m − B B− B
• Base case: m = 0. We have that A −1 | m =0 = A −1 = 0 = C ( 0) .
• Inductive case: assuming that it is true for m, let us show it is also true for m + 1.
m
By induction hypothesis, C (m) = BAA−−1 B . Then:
(c) After m calls to function reserve on an initially empty vector, the capacity of the vector is
m
of C (m) = BAA−−1 B elements. So the number of calls to reserve after n calls to push back is
the least m such that BA m − B
A −1 ≥ n, that is, ⌈log A ( n( A−B1)+ B )⌉. Since A and B are constants,
m is Θ(log n).
return r ;
}
The cost in time is Θ(n), since the vector is traversed 3 times, and each iteration of these
traversals only requires constant time. The cost in space of the auxiliary memory is
dominated by vector w, which has size n. Hence the cost in space is Θ(n).
(b) The function transposes the two subvectors of a from l to p and from p + 1 to r: if before
the call a[l..r] is Al , . . . , A p , A p+1, . . . , Ar , then after the call a[l..r] is A p+1 , . . . , Ar , Al , . . . , A p .
(c) Solution:
int stable partition (int x, vector<int>& a) {
return stable partition rec (x, a , 0, a . size ()−1);
}
if ( l == r) {
if (a[ l ] ≤ x) return l ;
else return l −1;
}
int m = ( l+r)/2;
int p = stable partition rec (x, a , l , m);
int q = stable partition rec (x, a , m+1, r );
mystery(a , p+1, m, q );
return p+q−m;
}
Let C (n) be the cost of function stable partition rec on a vector of size n = r − l + 1 in
the worst case. On the one hand two recursive calls are made on vectors of size n/2. On
the other, the cost of the non-recursive work is dominated by function mystery, which
takes time which is linear in the size of the vector that is being transposed. Using the
hypothesis of the statement (which happens, for example, in a vector in which elements
smaller and bigger than x alternate successively), this vector has size Θ(n). So we have
the recurrence C (n) = 2C (n/2) + Θ(n), which by the master theorem of divisive recur-
rences has solution Θ(n log n). In conclusion, the cost of function stable partition on a
vector of size n in the worst case is Θ(n log n).
170 Solutions to Mid Term Exams
(a) The value b[y] counts the number of elements of the sequence a that are less than or
equal to y.
(b) A possible solution:
int median(int n, const vector<int>& b) {
int l = 0;
int r = b. size () − 1;
while (l 6= r−1) {
int q = ( l+r)/2;
if (2* b[q] < n) l = q;
else r = q;
}
return r ;
}
(c) At each iteration of the loop, the value r − l is reduced by half. As initially l = 0 and
r = m, we have that Θ(log m) iterations are performed. And since each iteration has
a constant cost (arithmetic operations with integers, vector accesses, etc.), we conclude
that the cost of the function is Θ(log m).
(b) The cost C (n) of the recursive function exp as a function of n is determined by the re-
currence C (n) = C (n/2) + Θ(1): a single recursive call is made over a problem of size
n/2, and the rest of the operations have constant cost. By applying the master theorem
of divisive recurrences, we have that the solution is C (n) = Θ(log n) as required.
(b) By applying the master theorem of subtractive recurrences for solving the recurrence
U (m) = U (m − 1) + m, we have that U (m) = Θ(m2 ).
(c) As U (m) = Θ(m2 ) i U (m) = T (2m ), we have that T (n) = T (2log n ) = U (log n) = Θ((log n)2 ).
172 Solutions to Mid Term Exams
2 2 2
f (n) nn n
log ( n ) lim
n
log ( n2n )
lim = lim 2n = lim 2 22n = 2 n→∞ 2 =0
n →∞ g( n ) n→∞ 2 n→∞
since
2
nn n2 2n 2 n
lim log( 2 n ) = lim (log( n ) − log(2 )) = lim ( n log n − 2 ) = − ∞
n→∞ 2 n→∞ n→∞
1 1 1 1
· Θ( n4 ) + · Θ( n3 ) + (1 − 3 − ) · Θ( n ) = Θ( n ) + Θ( n2 ) + Θ( n ) = Θ( n2 )
n3 n n n
(c) By using the Master Theorem of divisive recurrences we have that a√= 2, b = 4, α =
log4 2 = 12 and k = 21 . So α = k, and therefore T (n) = Θ(nα · log n) = Θ( n · log n).
(a) The base case for k = 0 is true: A0 · x0 = x0 = x(0). For the inductive case, when k > 0,
we have by induction hypothesis that x(k − 1) = Ak−1 · x0 . So x(k) = A · x(k − 1) =
A · ( A k − 1 · x0 ) = ( A · A k − 1 ) · x0 = A k · x0 .
(b) In the first place Ak is computed using the algorithm of fast exponentiation in time
Θ(log k) (since n is constant). Then the result of multiplying Ak times x0 is returned,
which can be done in time Θ(1) (again, as n is constant). The cost in time of the algo-
rithm is then Θ(log k).
(c) x · y =
Solutions to Mid Term Exams 173
x2 y2 · 34n/3
+( x1 y2 + x2 y1 ) · 33n/3
+(( x0 + x1 + x2 ) · (y0 + y1 + y2 ) − x2 y2 − ( x1 y2 + x2 y1 ) − ( x1 y0 + x0 y1 ) − x0 y0 ) · 32n/3
+( x1 y0 + x0 y1 ) · 3n/3
+ x0 y0
We use 7 products.
(d) To compute the product of x and y of n digits, the algorithm computes recursively ( x0 +
x1 + x2 ) · (y0 + y1 + y2 ), x2 y2 , x1 y2 + x2 y1 , x1 y0 + x0 y1 and x0 y0 , which are products
of numbers of n/3 digits. Then x · y is computed using the equation of the previous
section. As numbers are represented in base 3, to multiply by a power of 3 consists
in adding zeroes to the right and can be done in time Θ(n). The involved additions
can also be done in time Θ(n). Therefore the cost T (n) satisfies the recurrence T (n) =
7T (n/3) + Θ(n), which has solution Θ(nlog3 7 ).
(a) We define function U (m) = T (bm ). Then T (n) = U (logb (n)). Moreover, we have:
U (m) = T (bm ) = T (bm /b) + Θ(logk (bm )) = T (bm−1 ) + Θ(mk logk (b)) =
= T ( b m − 1 ) + Θ ( m k ) = U ( m − 1) + Θ ( m k )
The Master Theorem of subtractive recurrences claims that if we have a recurrence of
the form U (m) = U (m − c) + Θ(mk ) with c > 0 and k ≥ 0, then U (m) = Θ(mk+1 ). So the
solution to the recurrence of the statement is T (n) = Θ((logb (n))k+1 ) = Θ(logk+1 n).
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10)
TRUE X X X X X X
FALSE X X X X
(a) The cost in the worst case is Θ(n3 ). The worst case always happens.
(b) The cost in the best case is Θ(n2 ). The best case happens, for example, when the two
matrices only have true in their coefficients.
The cost in the worst case is Θ(n3 ). The worst case happens, for example, when the two
matrices only have false in their coefficients.
(c) The function considers the Boolean matrices as matrices of integers, in which false is
interpreted as 0 and true as 1. Then we apply Strassen’s algorithm for the product of
matrices. Let M be the resulting matrix. The coefficient of the i-th row and j-th column
of M is
n −1
mij = ∑ (aik · bkj ).
k=0
As the coefficients of the input matrices are 0 or 1, the product as integer numbers is the
same as the logical ∧ operation. So mij counts the number of pairs ( aik , bkj ) where both
aik and bkj are true at the same time. Therefore, to obtain the logical product we only
have to define pij as 1 if mij > 0, and 0 otherwise. The cost is dominated by Strassen’s
algorithm, which has cost Θ(nlog2 7 ) ≈ Θ(n2.8 ).
√
(a) Given an integer n ≥ 0, function mystery computes ⌊ n⌋.
(b) First of all we find the cost C ( N ) of the function mystery rec in terms of the size N =
r − l + 1 of the interval [l, r]. This cost follows the recurrence C ( N ) = C ( N/2) + Θ(1),
as at each call a recursive call is made on an interval with half the elements, and there is
additional non-recursive work with constant cost. According to the master theorem of
divisive recurrences, the solution to this recurrence is Θ(log N ). As mystery(n) consists
in calling mystery rec (n, 0, n+1), we can conclude that the cost of mystery(n) is Θ(log n).
Solutions to Mid Term Exams 175
(a) Θ(n)
(b) Θ(n2 )
(c) Θ(n log n)
(d) Θ(n log n)
(e) A possible solution:
void my sort(vector<int>& v) {
int n = v. size ();
double lim = n * log (n );
int c = 0;
for (int i = 1; i < n; ++i) {
int x = v[ i ];
int j ;
for ( j = i ; j > 0 and v[j − 1] > x; −−j) {
v[ j ] = v[ j − 1];
++c;
}
v[ j ] = x;
if (c > lim) {
merge sort (v );
return;
}
}
}
(f) First of all we observe that, as the outermost for loop makes n − 1 iterations, each of
which has cost Ω(1), the cost of the overall execution is Ω(n).
If for example the vector is already sorted in increasing order, then my sort behaves as
insertion sort: the innermost for loop is never entered, c is always 0, and merge sort is
not called. As each iteration of the outermost for loop has constant cost, the cost in this
case is Θ(n). So the cost of my sort in the best case is Θ(n).
To see the cost in the worst case, we distinguish two cases:
• Suppose that merge sort is not called. Then the cost is proportional to the final
value of variable c. As merge sort is not called, we have that c ≤ n ln n, and the cost
is O(n ln n) = O(n log n).
• Suppose that merge sort is eventually called. If it is called at the end of the first
iteration of the outermost for loop, then the cost is O(n) from the innermost for
loop plus Θ(n log n) of the merge sort. Altogether, the cost is Θ(n log n).
If merge sort is called at the end of the second, or third, etc. iteration of the out-
ermost for loop, then merge sort was not called at the previous iteration of the
outermost for loop. Moreover, in the last iteration c may have increased in i at
most, so when merge sort is called we have that n ln n < c ≤ i + n ln n ≤ n + n ln n ≤
n ln n + n ln n = 2n ln n (for n big enough), and hence c = Θ(n log n). Since the cost
of merge sort is Θ(n log n), altogether the cost is Θ(n log n).
176 Solutions to Mid Term Exams
The worst case happens for example when the vector is sorted backwards, that is, in
decreasing order. As in this case insertion sort has cost Θ(n2 ), at some point of the
execution of my sort the subprocedure merge sort will be called, and by the previous
reasoning the cost will be Θ(n log n).
5
Solutions to Lab Exams
178 Solutions to Lab Exams
Shift 1
Solution to problem 1
#include <iostream>
#include <vector>
#include <queue>
#include <cassert>
struct Pos {
int i , j ;
Pos(int ii = −1, int jj = −1) : i ( ii ), j ( jj ) { }
};
int search (const vector < vector<char> >& map, int n, int m, int i0 , int j0 ) {
const int MINFTY = −1;
vector< vector<int> > dist(n, vector<int> (m, MINFTY));
queue<Pos> q;
int max dist = MINFTY;
q.push(Pos(i0 , j0 ));
dist [ i0 ][ j0 ] = 0;
while (not q.empty()) {
Pos p = q. front ();
q.pop ();
int i = p. i ;
int j = p. j ;
for(int k = 0; k < N DIRS; ++k) {
int ii = i + di [k ];
int jj = j + dj [k ];
if (ok(n,m, ii , jj ) and map[ii][ jj ] 6= 'X' and dist [ ii ][ jj ] == MINFTY) {
q.push(Pos( ii , jj ));
dist [ ii ][ jj ] = 1 + dist [ i ][ j ];
if (map[ii ][ jj ] == ' t ' ) max dist = dist [ ii ][ jj ];
}
}
Solutions to Lab Exams 179
}
return max dist ;
}
int main(void) {
int n, m;
cin >> n >> m;
vector < vector<char> > map(n, vector<char>(m));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
cin >> map[i][j ];
int f , c ;
cin >> f >> c;
−−f;
−−c;
int dist = search (map, n, m, f , c );
if ( dist ≥ 0) cout << ”distancia maxima: ” << dist << endl;
else cout << ”no es pot arribar a cap tresor” << endl;
}
Solution to problem 2
#include <iostream>
#include <vector>
0 ≤ j and j < n;
}
int main(void) {
int n, r ;
cin >> n >> r;
Mat m(n, Vec(n, false ));
search (0, 0, n, r , 0, m);
}
Solutions to Lab Exams 181
Shift 2
Solution to problem 1
#include <iostream>
#include <string>
#include <map>
int main(void) {
map<string, int> bagmul;
string command;
while (cin >> command) {
if (command == ”store”) {
string word;
cin >> word;
pair < Iterator , bool> res = bagmul. insert ( pair <string,int>(word, 1));
if (not res . second) ++bagmul[word];
}
else if (command == ”delete”) {
string word;
cin >> word;
Iterator i = bagmul.find(word);
if ( i 6= bagmul.end()) {
if ( i −>second == 1) bagmul.erase ( i );
else −−bagmul[word];
}
}
else if (command == ”minimum?”) {
if (bagmul.empty()) cout << ”indefinite minimum” << endl;
else {
Iterator i = bagmul.begin ();
cout << ”minimum: ”
<< i−> first << ”, ”
<< i−>second << ” time(s)” << endl;
}
}
else {
if (bagmul.empty()) cout << ”indefinite maximum” << endl;
else {
Iterator i = bagmul.end ();
−−i;
cout << ”maximum: ”
<< i−>first << ”, ”
<< i−>second << ” time(s)” << endl;
}
182 Solutions to Lab Exams
}
}
}
Solution to problem 2
#include <iostream>
#include <vector>
struct Point {
int r , c ;
Point(int rr , int cc) : r( rr ), c(cc ) { }
};
void search (int re , int ce , int n, int m, const CMat& t, vector<Point>& v, BMat& seen) {
Point p = v.back ();
if (p. r == re and p.c == ce) {
for (int i = 0; i < v. size (); ++i)
cout << t[v[ i ]. r ][ v[ i ]. c ];
cout << endl;
}
else {
for (int k = 0; k < N DIRS; ++k) {
int rr = p. r + DR[k];
int cc = p.c + DC[k];
if (ok( rr , cc , n, m) and not seen[rr ][ cc ]) {
seen [ rr ][ cc] = true;
v.push back(Point( rr , cc ));
search ( re , ce , n, m, t , v, seen );
v.pop back ();
seen [ rr ][ cc] = false ;
Solutions to Lab Exams 183
}
}
}
}
int main(void) {
int n, m;
cin >> n >> m;
CMat t (n, CVec(m));
BMat seen(n, BVec(m, false ));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
cin >> t[i ][ j ];
int ri , ci , re , ce ;
cin >> ri >> ci >> re >> ce;
seen [ ri ][ ci ] = true;
vector<Point> v(1, Point( ri , ci ));
search ( re , ce , n, m, t , v, seen );
}
184 Solutions to Lab Exams
Solution to problem 1
#include <iostream>
#include <vector>
struct Point {
int r , c ;
Point(int rr , int cc) : r( rr ), c(cc ) {}
};
int main(void) {
int n, m;
while (cin >> n >> m) {
Solutions to Lab Exams 185
Solution to problem 2
#include <iostream>
#include <set>
int main(void) {
lint suma = 0;
set <lint> selec ;
set <lint> resta ;
int n;
cin >> n;
string op;
lint val ;
while (cin >> op >> val) {
if (op == ”deixar”) {
186 Solutions to Lab Exams
Solution to problem 1
#include <iostream>
#include <vector>
int search (const MC& map, int n, int m, int i , int j , MB& marked) {
int t = 0;
if (map[i][ j ] == ' t ' ) ++t;
marked[i ][ j ] = true;
for (int k = 0; k < N DIRS; ++k) {
int ii = i + DI[k ];
int jj = j + DJ[k ];
if (ok(n, m, ii , jj ) and map[ii][ jj ] 6= 'X' and not marked[ii ][ jj ])
t += search (map, n, m, ii , jj , marked);
}
return t ;
}
int main(void) {
int n, m;
cin >> n >> m;
MC map(n, VC(m));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
cin >> map[i][j ];
int f , c ;
cin >> f >> c;
Solution to problem 2
#include <iostream>
#include <vector>
int main() {
int n;
cin >> n;
string s(n, ' X' );
b (0, n, s );
}
Solutions to Lab Exams 189
Solution to problem 1
#include<iostream>
#include<string>
#include<map>
int main() {
string s ;
map<string,string> liats ;
while(cin >> s) {
if (s == ”info”) {
cout << ”PARELLES:” << endl;
for ( ite it = liats . begin (); it 6= liats . end (); ++it)
if ( it −>second 6= ”” and it−>first < it−>second)
cout << it −>first << ” ” << it −>second << endl;
cout << ”SOLS:” << endl;
for ( ite it = liats . begin (); it 6= liats . end (); ++it)
if ( it −>second == ””)
cout << it −>first << endl;
cout << ”−−−−−−−−−−” << endl;
}
else {
string x, y;
cin >> x >> y;
if ( liats [x] 6= ””) liats [ liats [x]] = ””;
if ( liats [y] 6= ””) liats [ liats [y]] = ””;
liats [x] = y;
liats [y] = x;
}
}
}
Solution to problem 2
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
int main() {
int f , c ;
while (cin >> f >> c) {
vector<vector<char> > M(f, vector<char> (c));
pair <int, int> p;
queue<pair<int,int> > F;
for (int i = 0; i < f ; ++i) {
for (int j = 0; j < c; ++j) {
cin >> M[i][j ];
if (M[i][j ] == 'P' ) {p. first = i ; p.second = j ;}
if (M[i][j ] == 'F' ) F.push(make pair( i , j ));
}
}
while (not F.empty()) {
int i = (F. front ()). first ;
int j = (F. front ()). second ;
F.pop ();
for (int k = 0; k < 8; ++k) M[i+xf[k ]][ j+yf[k ]] = ' X' ;
}
if ( cerca bolet (M,p)) cout << ”si” << endl;
else cout << ”no” << endl;
}
}
Solutions to Lab Exams 191
Solution to problem 1
#include <iostream>
#include <sstream>
#include <vector>
#include <queue>
string op;
while (cin >> op) {
if (op == ”SURT”) {
int idx ;
cin >> idx;
−−idx;
if (0 ≤ idx and idx < v. size () and not v[idx ]. empty()) {
cout << v[idx ]. front () << endl;
v[idx ]. pop ();
}
}
else {
string name;
int idx ;
cin >> name >> idx;
−−idx;
if (0 ≤ idx and idx < v. size ())
v[idx ]. push(name);
}
}
192 Solutions to Lab Exams
int main() {
int n;
cin >> n;
string line ;
getline (cin, line ); // Read empty line.
VQS v;
read queues (n, v );
process exits (v );
write final contents (v );
}
Solution to problem 2
#include <iostream>
#include <vector>
#include <queue>
void compute topological ordering (const VVI& g, VI& indeg, VI& ord) {
int n = g. size ();
priority queue <int, vector<int>, greater<int> > pq;
for (int u = 0; u < n; ++u)
if (indeg[u] == 0) pq.push(u);
ord = VI(n);
int cnt = 0;
while (not pq.empty()) {
Solutions to Lab Exams 193
int main() {
int n, m;
while (cin >> n >> m) {
VVI g(n);
VI indeg(n, 0);
for (int k = 0; k < m; ++k) {
int u, v;
cin >> u >> v;
g[u ]. push back(v );
++indeg[v];
}
VI ord ;
compute topological ordering (g, indeg , ord );
write (ord );
}
}
194 Solutions to Lab Exams
Solution to problem 1
#include <iostream>
#include <vector>
int n, m;
VI div ;
bool ok(int y) {
for (int i = 0; i < m; ++i)
if (y % div[i ] == 0)
return false ;
return true;
}
int main() {
while (cin >> n >> m) {
div = VI(m);
for (int i = 0; i < m; ++i)
cin >> div[i ];
backtracking (0, 0);
cout << ”−−−−−−−−−−” << endl;
}
}
Solution to problem 2
#include <iostream>
#include <vector>
#include <queue>
Solutions to Lab Exams 195
typedef pair<int,int> P;
int main() {
int n, m;
while (cin >> n >> m) {
VVC t(n, VC(m));
int f0 , c0;
cin >> f0 >> c0;
int dist = distance ( f0 −1, c0−1, t );
if ( dist == +oo) cout << ”no” << endl;
else cout << dist << endl;
}
}
Solutions to Lab Exams 197
Solution to problem 1
#include <iostream>
#include <vector>
#include <queue>
struct Pos {
int i , j ;
Pos(int ii , int jj ) : i ( ii ), j ( jj ) { }
};
int bfs (const vector < vector<char> >& map, int i0, int j0) {
int n = map . size ();
int m = map[0]. size ();
queue<Pos> q;
q.push( Pos(i0 , j0 ) );
vector< vector<int> > dist(n, vector<int>(m, UNDEF));
dist [ i0 ][ j0 ] = 0;
while (not q.empty()) {
Pos p = q. front ();
q.pop ();
int i = p. i ;
int j = p. j ;
if (map[i][ j ] == ' t ' ) return dist [ i ][ j ];
else {
for(int k = 0; k < N DIRS; ++k) {
int ii = i + DI[k ];
int jj = j + DJ[k ];
if (ok(n, m, ii , jj ) and map[ii][ jj ] 6= 'X' and dist [ ii ][ jj ] == UNDEF) {
q. push( Pos( ii , jj ) );
dist [ ii ][ jj ] = 1 + dist [ i ][ j ];
}
}
198 Solutions to Lab Exams
}
}
return UNDEF;
}
int main(void) {
int n, m;
cin >> n >> m;
int f , c ;
cin >> f >> c;
Solution to problem 2
#include <iostream>
#include <vector>
#include <map>
#include <assert.h>
else {
int v = v2s. size ();
v2s.push back(s );
s2v. insert (make pair(s , v ));
return v;
}
}
int main() {
n outputs = n inputs = 0;
string token ;
string s ;
cin >> s;
int ov = string2vertex (s );
if (ov+1 > gdir. size ()) gdir . resize (ov+1);
cin >> s;
int iv1 = string2vertex (s );
if (iv1 + 1 > ginv. size ()) ginv. resize (iv1 + 1);
if ( token == ”NOT”) {
gdir [ov ]. push back(iv1 );
ginv[iv1 ]. push back(ov );
}
else {
cin >> s;
int iv2 = string2vertex (s );
if (iv2 + 1 > ginv. size ()) ginv. resize (iv2 + 1);
if ( token == ”AND”) {
gdir [ov ]. push back( min(iv1, iv2) );
200 Solutions to Lab Exams
VI bag;
for (int v = n outputs ; v < n inputs + n outputs ; ++v)
bag.push back(v );
VI ord ;
while (not bag.empty()) {
int v = bag.back ();
ord . push back(v );
bag.pop back ();
for (auto w : ginv[v]) {
−−ddir[w];
if ( ddir [w] == 0)
bag.push back(w);
}
}
VB val(n );
while (cin >> token) {
val [ n outputs ] = (token == ”T”);
for (int v = n outputs+1; v < n inputs + n outputs ; ++v) {
cin >> token;
val [v] = (token == ”T”);
}
}
}
cout << (val [0] ? ' T' : ' F' );
for (int v = 1; v < n outputs; ++v)
cout << ' ' << (val[v] ? ' T' : ' F' );
cout << endl;
}
}
202 Solutions to Lab Exams
Solution to problem 1
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int n, m;
while (cin >> n >> m) {
VVI g(n);
for (int k = 0; k < m; ++k) {
int x, y;
cin >> x >> y;
g[x ]. push back(y );
}
for (int x = 0; x < n; ++x)
sort (g[x ]. begin (), g[x ]. end ());
Solution to problem 2
#include <iostream>
#include <vector>
int main() {
int n;
cin >> n;
string w(n, ' a' );
VB mkd(n, false );
bt (0, n, w, mkd);
}
204 Solutions to Lab Exams
Solution to problem 1
#include <iostream>
#include <vector>
int main() {
int n, m;
while (cin >> n >> m) {
VVI g(n);
for (int k = 0; k < m; ++k) {
int x, y;
cin >> x >> y;
g[x ]. push back(y );
Solutions to Lab Exams 205
Solution to problem 2
#include <iostream>
#include <vector>
int bt (int k , const VI& m, int x, int sum par, int max und) {
if (sum par > x or sum par + max und < x) return 0;
if (k == m.size ()) return 1;
int cnt = 0;
for (int v = 0; v ≤ 2; ++v)
cnt += bt(k+1, m, x, sum par + v*m[k], max und − 2*m[k]);
return cnt ;
}
int main() {
int x, n;
while (cin >> x >> n) {
VI m(n);
int s = 0;
for (int k = 0; k < n; ++k) {
cin >> m[k];
s += m[k];
}
cout << bt(0, m, x, 0, 2* s) << endl;
}
}
206 Solutions to Lab Exams
Solution to problem 1
#include <iostream>
#include <vector>
return max(nl, no );
}
int main() {
int n, m;
while (cin >> n >> m) {
VVC sol(n, VC(m));
cout << bt(0, 0, sol , 0) << endl;
}
}
Solutions to Lab Exams 207
Solution to problem 2
#include <iostream>
#include <vector>
bool possible (int i ini , int j ini , int i fin , int j fin , const VVC& t, VVB& mkd) {
if (mkd[ i ini ][ j ini ]) return false ;
mkd[ i ini ][ j ini ] = true;
if ( i ini == i fin and j ini == j fin ) return true;
for (int k = 0; k < 4; ++k) {
int i = i ini + di [k ];
int j = j ini + dj [k ];
if (ok( i , j , t ) and possible ( i , j , i fin , j fin , t , mkd)) return true;
}
return false ;
}
int main() {
int n, m;
while (cin >> n >> m) {
VVC t(n, VC(m));
int i ini , j ini , i fin , j fin ;
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
cin >> t[i ][ j ];
i fin = i ;
j fin = j ;
}
else if ( t [ i ][ j ] == 'M') {
t [ i ][ j ] = ' X' ;
if ( i −1 ≥ 0 and t[i−1][ j ] 6= 'M') t [ i −1][ j ] = ' X' ;
if ( i+1 < n and t[ i+1][ j ] 6= 'M') t [ i+1][ j ] = ' X' ;
if ( j −1 ≥ 0 and t[ i ][ j −1] 6= 'M') t [ i ][ j −1] = 'X' ;
if ( j+1 < m and t[ i ][ j+1] 6= 'M') t [ i ][ j+1] = ' X' ;
}
Solution to problem 1
#include <iostream>
#include <vector>
#include <queue>
const vector<pair<int, int>> DIRS = { {1, 0}, {−1, 0}, {0, 1}, {0, −1} };
const int UNDEF = −1;
int dist 2on tresor mes llunya (int i0 , int j0 , vector<vector<char>>& mapa) {
int max dist = UNDEF;
int max dist2 = UNDEF;
queue<pair< pair<int, int>, int >> q;
q.push({{i0 , j0 }, 0});
mapa[i0][ j0 ] = ' X' ;
while (not q.empty()) {
int i = q. front (). first . first ;
int j = q. front (). first . second ;
int d = q. front (). second ;
q.pop ();
for (auto dir : DIRS) {
int ii = i + dir . first ;
int jj = j + dir . second ;
if (mapa[ii ][ jj ] 6= 'X') {
if (mapa[ii ][ jj ] == ' t ' ) {
max dist2 = max dist ;
max dist = d+1;
}
q.push({{ ii , jj }, d+1});
mapa[ii ][ jj ] = ' X' ;
}
}
}
return max dist2 ;
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<char>> mapa(n+2, vector<char>(m+2, 'X'));
for (int i = 1; i ≤ n; ++i)
for (int j = 1; j ≤ m; ++j)
cin >> mapa[i][j ];
210 Solutions to Lab Exams
int f , c ;
cin >> f >> c;
Solution to problem 2
#include <iostream>
#include <vector>
int main() {
int f , c ;
cin >> f >> c;
vector<int> col( f );
vector<bool> marked(c, false);
torres ( f , c , 0, col , marked);
}
Solutions to Lab Exams 211
Solution to problem 1
#include <iostream>
#include <vector>
#include <queue>
typedef pair<int,int> P;
int main(void) {
int n, m;
while (cin >> n >> m) {
vector<vector<P>> g(n);
for (int k = 0; k < m; ++k) {
int x, y, c ;
cin >> x >> y >> c;
−−x;
−−y;
g[x ]. push back(P(c, y ));
g[y ]. push back(P(c, x ));
}
vector<bool> mkd(n, false);
mkd[0] = true;
priority queue <P, vector<P>, greater<P> > pq;
for (P x : g [0]) pq.push(x );
int sz = 1;
int sum = 0;
while (sz < n) {
int c = pq. top (). first ;
int x = pq. top (). second ;
pq.pop ();
if (not mkd[x]) {
mkd[x] = true;
for (P y : g[x]) pq.push(y );
sum += c;
++sz;
}
}
cout << sum << endl;
}
}
Solution to problem 2
212 Solutions to Lab Exams
#include <vector>
Shift 1
Solution to problem 1
#include <iostream>
#include <vector>
vector<vector<int>> su;
vector<vector<bool>> r mkd, c mkd;
vector<vector<vector<bool>>> s mkd;
void write () {
cout << endl;
for (int i = 0; i < 9; ++i) {
cout << su[i ][0] + 1;
for (int j = 1; j < 9; ++j)
cout << ' ' << su[i ][ j ] + 1;
cout << endl;
}
}
int main() {
su = vector<vector<int>>(9, vector<int>(9));
int n;
cin >> n;
cout << n << endl;
while (n−−) {
r mkd = c mkd = vector<vector<bool>>(9, vector<bool>(9, false));
s mkd = vector<vector<vector<bool>>>(3, vector<vector<bool>>(3, vector<bool>(9, false)));
for (int i = 0; i < 9; ++i)
214 Solutions to Lab Exams
Solution to problem 2
#include <iostream>
#include <vector>
#include <algorithm>
Shift 2
Solution to problem 1
#include <iostream>
#include <vector>
int m, n;
vector<int> l;
int main() {
cin >> m >> n;
l = vector<int>(n);
for (int& x : l ) cin >> x;
gen (0, 0);
}
Solution to problem 2
#include <iostream>
b [0][0] = b [1][1] = 1;
b [0][1] = b [1][0] = 0;
}
if (n == 0)
identity (b );
else {
if (n%2 == 0) {
Matrix c ;
power(n/2, m, a , c );
product(m, c , c , b );
}
else {
Matrix c , d;
power(n/2, m, a , c );
product(m, c , c , d );
product(m, a , d, b );
}
}
}
int main() {
Matrix a ;
a [0][0] = 1; a [0][1] = 1;
a [1][0] = 1; a [1][1] = 0;
int n, m;
while (cin >> n >> m) {
Matrix b;
power(n, m, a , b );
cout << b[1][0] << endl;
}
}
Solutions to Lab Exams 217
Solution to problem 1
#include <iostream>
#include <vector>
int main() {
int n;
cin >> n;
vector<vector<bool>> mkd(2, vector<bool>(n, false));
vector<string> let (2);
cin >> let [CON] >> let[VOC];
string sol (2* n, ' ' ); // Need a char for filling.
g (0, n, let , sol , mkd);
}
Solution to problem 2
#include <iostream>
#include <vector>
#include <unordered set>
#include <queue>
int main() {
218 Solutions to Lab Exams
int n, t ;
while (cin >> n >> t) {
vector<unordered set<int>> g(n);
while (−−t ≥ 0) {
int s ;
cin >> s;
vector<int> pub(s);
for (int i = 0; i < s; ++i)
cin >> pub[i ];
Solution to problem 1
#include <iostream>
#include <vector>
int main() {
int n, p;
cin >> n;
vector<string> s(n);
for (auto& x : s) cin >> x;
cin >> p;
vector<int> sol(n);
g (0, n, p, s , sol );
}
Solution to problem 2
#include <iostream>
#include <vector>
#include <queue>
220 Solutions to Lab Exams
typedef pair<int,int> P;
int main() {
int n, m;
while (cin >> n >> m) {
vector< vector<P> > g(n);
int tot = 0;
for (int k = 0; k < m; ++k) {
int x, y, c ;
cin >> x >> y >> c;
g[x ]. push back({c , y });
g[y ]. push back({c , x });
tot += c;
}
vector<bool> mkd(n, false);
mkd[0] = true;
priority queue <P, vector<P>, greater<P> > pq;
for (P p : g [0])
pq.push(p );
int sz = 1;
int sum = 0;
while (sz < n) {
int c = pq. top (). first ;
int x = pq. top (). second ;
pq.pop ();
if (not mkd[x]) {
mkd[x] = true;
for (P p : g[x])
pq.push(p );
sum += c;
++sz;
}
}
cout << tot − sum << endl;
}
}
Solutions to Lab Exams 221
Solution to problem 1
#include <iostream>
#include <vector>
int n, m;
VVI g;
VI c ;
int main() {
while (cin >> n >> m) {
g = VVI(n);
for (int k = 0; k < m; ++k) {
int x, y;
cin >> x >> y;
g[x ]. push back(y );
g[y ]. push back(x );
}
c = VI(n, UNDEF);
if ( two colorable (0)) cout << ”yes” << endl;
else cout << ”no” << endl;
}
}
222 Solutions to Lab Exams
Solution to problem 2
#include <iostream>
#include <vector>
#include <algorithm>
class Permutation {
vector<int> v;
public:
Permutation(int n) : v( n ) { }
Permutation(const Permutation& s) : v(s . v) { }
void pow(int k) {
if (k == 0)
for (int i = 0; i < v. size (); ++i)
v[ i ] = i ;
else {
Permutation s = * this ;
s . pow(k/2);
if (k % 2 == 0) {
* this = s ;
* this *= s ;
}
else {
* this *= s ;
* this *= s ;
}
}
}
};
Solutions to Lab Exams 223
int main() {
int n;
while (cin >> n) {
Permutation p(n );
for (int i = 0; i < n; ++i) {
cin >> p[i ];
}
int k ;
cin >> k;
p.pow(k);
Solution to problem 1
#include <iostream>
#include <vector>
#include <algorithm>
bool bin search (bool inc , const vector<int>& v, int l , int r , int x) {
if ( l == r) return v[ l ] == x;
int m = (l+r)/2;
bool cond;
if ( inc ) cond = (x ≤ v[m]);
else cond = (x ≥ v[m]);
if (cond) return bin search ( inc , v, l , m, x );
else return bin search ( inc , v, m+1, r, x );
}
Solution to problem 2
#include <iostream>
#include <queue>
#include <climits>
int main() {
int n, m;
cin >> n >> m;
vector<int> z(n);
for (int& x : z) cin >> x;
vector<vector<P>> g(n);
while (m−−) {
int u, v, w;
cin >> u >> v >> w;
g[u ]. push back({v, w});
g[v ]. push back({u, w});
}
int a , b;
while (cin >> a >> b) {
int c = cost (g, z , a , b );
cout << ”c(” << a << ”,” << b << ”) = ”;
if (c == +oo ) cout << ”+oo” << endl;
else cout << c << endl;
}
}
6
Solutions to Final Exams
228 Solutions to Final Exams
(a) The master theorem for dividing recurrences claims that if we have a recurrence of the
form T (n) = aT (n/b) + Θ(nk ) with a > 0, b > 1 and k ≥ 0, then, letting α = logb a,
k
Θ( n )
if α < k,
T (n) = Θ(nk log n) if α = k,
Θ( n α ) if α > k.
(b) 2
(c) priority queue <T>’s are implemented with max-heaps. If there existed a function
T& top ();
then a user of the class could modify the root of the heap and break the invariant that
each node is greater than or equal to its children.
(a) Yes
(b) No (leaves must be black)
(c) No (the children of a red node must be black)
(d) Yes
(e) No (it must be a binary search tree)
(f) No (the number of black nodes in a path from the root to a leaf must be constant)
(a) Let C (n) be the cost of the algorithm in the worst case as a function of n. Then:
• If s ≥ 21 : C (n) = C (sn) + Θ(1)
As 0 < s < 1, we have 0 < max(s, 1 − s) < 1, and so max(1s,1−s) > 1. By applying the
master theorem for dividing recurrences we have that α = k = 0, and therefore the cost
is Θ(log n) (independently of s).
Solutions to Final Exams 229
ω π ( u0 , . . . , u k ) = ω π ( u0 , u1 ) + ω π ( u1 , . . . , u k )
= ω π ( u0 , u1 ) + ω ( u1 , . . . , u k ) − π ( u1 ) + π ( u k )
= ω ( u0 , u1 ) − π ( u0 ) + π ( u1 ) + ω ( u1 , . . . , u k ) − π ( u1 ) + π ( u k )
= ω ( u0 , u1 ) − π ( u0 ) + ω ( u1 , . . . , u k ) + π ( u k )
= ω ( u0 , . . . , u k ) − π ( u0 ) + π ( u k )
(f) If π is a potential, then the reduced weights ωπ are non-negative. So we can apply
Dijkstra’s algorithm to compute the distances with weights ωπ from s to all vertices.
Then we can compute the distances with weights ω using the following observation: if
u, v ∈ V i c is the minimum path with weights ω from u to v (which exists by hypothesis),
then c is the minimum path with weights ωπ from u to v and ω (c) = ωπ (c) + π (u) −
π ( v).
232 Solutions to Final Exams
79
55 73
36 52 45 71
18 12 13
(b) To prove that P ⊆ co-NP we only need to see that if L is a problem from class P, then its
complement L belongs to NP. But if L is from P then there is a deterministic polynomial
algorithm A that decides L. Let us consider now the algorithm A that does the same as
A, but returns 1 when A returns 0, and returns 1 when A returns 0. Then A decides L,
and since A takes polynomial time, we have L ∈ P ⊆ NP.
(c) The cost C (n) of f in function of n follows the recurrence
as there are 3 recursive calls on subvectors of size n/3 and additionally operations of
constant cost are performed. By the Master Theorem of Divisive Recurrences, the solu-
tion to the recurrence is C (n) = Θ(n).
(d) It is not true. For example, n2n = (nn )2 grows asymptotically faster than nn .
We must use a dictionary with integer keys implemented with a hash table, and a vector
which is initially empty that will contain the intersection.
First of all we pass over A and add all its elements to the dictionary. We make n insertions
to the dictionary, each of which takes time O(1) on average. So the first pass costs O(n) on
average.
In the second place we pass over B and, for each of its elements, we check if it already
belongs to the dictionary. If so, the element is added to the vector of the intersection with a
push back. Otherwise nothing is done. Hence we make m lookups to the dictionary, each of
which takes time O(1) on average. Since each push back takes constant time, the cost of the
second pass is O(m) on average.
In total, the cost is O(n + m) on average.
queue<int> Q;
for (int u = 0; u < n; ++u)
if (pred[u] == 0) {
Q.push(u);
lvl [u] = 0;
}
used[ i ] = false ;
}
}
};
int n, k ;
vector<int> perm;
vector<bool> used;
void write () {
cout << perm[1];
for (int i = 2; i ≤ n; ++i) cout << ' ' << perm[i];
cout << endl;
}
int main() {
cin >> n >> k;
perm = vector< int>(n+1);
used = vector<bool>(n+1, false);
generate (1, 0, 0);
}
(a) Given a string s of size n, function mystery computes the evaluation of s as a polynomial
in x: ∑in=−01 s[i ] · xi .
The value 0 would not be adequate for x if one wanted to use mystery as a hash function
because the function would always return s[0]; in other words, all strings that start with
the same character would have the same hash value.
(b) The answers:
(1) (2) (3) (4)
TRUE X X
FALSE X X
(c) The value returned by find(2) is 0. The value returned by find(9) is 5.
(d) In the worst case, the searched value is strictly greater than all values in the vector.
Hence at each recursive call the algorithm chooses the larger of the two parts, which
is 23 of the size of the interval [l, · · · , r]. Moreover, apart from the recursive call only
operations of constant cost are performed. So, if n = r − l + 1, the cost T (n) in the worst
case is determined by the recurrence T (n) = T ( 32 n) + Θ(1). By applying the master
theorem of divisive recurrences, we have that the solution to the recurrence is Θ(log n).
2
1 3
0
6
4
5
(a) priority queue <T>’s are implemented with max-heaps. If there existed a function
then a user of the class could modify the root of the heap and break the invariant that
each node is greater than or equal to its children.
(b)
A 0
B 110
C 10 A
D 111
C
B D
(c)
f s
c j r v
a d i m q u y
h x z
(d)
79
55 73
36 52 45 71
18 12 13
Solutions to Final Exams 241
(a) We define function U (m) = T (bm ). Then T (n) = U (logb (n)). Moreover, we have:
U (m) = T (bm ) = T (bm /b) + Θ(logk (bm )) = T (bm−1 ) + Θ(mk logk (b)) =
= T ( b m − 1 ) + Θ ( m k ) = U ( m − 1) + Θ ( m k )
The Master Theorem of subtractive recurrences claims that if we have a recurrence of
the form U (m) = U (m − c) + Θ(mk ) with c > 0 and k ≥ 0, then U (m) = Θ(mk+1 ). So the
solution to the recurrence of the statement is T (n) = Θ((logb (n))k+1 ) = Θ(logk+1 n).
(b) The problem of 3-colorability is NP-complete. Therefore, if the claim in the forum were
right, we would have a polynomial-time algorithm that solved an NP-complete prob-
lem, and so P = NP. Since up to now the problem of whether P = NP is still open (and,
moreover, the dominant conjecture is that it is false), what is said in the forum is not
plausible.
(b) It is only required to swap the recursive calls: that is, swap the two ifs (together with
their corresponding bodies) inside of the else.
Solutions to Final Exams 243
35
25 50
12 30 40 70
10 31 65 86
52
45 29
36 13 23 21
18 12
(c) Θ(n)
√
(d) Θ( n log n)
√
(e) Θ( n)
(f) The residual network:
1
v1 v3
4 3 3
s 1 2 2 t
2
6 1
v2 v4
1
(a) The function mystery computes the product of the polynomial p by the monomial c · xk .
Its cost in time is Θ(n + k).
244 Solutions to Final Exams
(b) The type unordered map<int,int> can be implemented with hash tables.
polynomial p0 q0 = p0 * q0;
polynomial p1 q1 = p1 * q1;
polynomial p1 q0 plus p0 q1 = (( p0 + p1) * (q0 + q1)) +
mystery(p0 q0 + p1 q1, −1, 0);
return p0 q0 +
mystery(p1 q0 plus p0 q1 , 1, n2) +
mystery(p1 q1, 1, n );
}
The function makes 3 recursive calls over polynomials of size Θ(n/2). Moreover, the
non-recursive work (additions, calls to function mystery) has cost Θ(n). If we call T (n)
the cost of the function in terms of n, then we obtain the recurrence T (n) = 3T (n/2) +
Θ(n). By applying the master theorem of divisive recurrences we obtain that the cost is
T (n) = Θ(nlog 3 ), which is better than Θ(n2 ).
(a) The efficiency bug consists is that every time we choose a new subset, we scan the whole
vector S again, without considering the previously chosen subsets. This means that we
Solutions to Final Exams 245
can take the same subset several times, or consider different permutations of the same
collection of subsets.
A possible way of fixing the code is to add a parameter that is the index of the first subset
that we need to consider in the following choice:
bool set cover rec (int f , int K, int N, const vector<set<int>>& S,
vector<int>& w, int c) {
if (c == N) return true;
if (K == 0) return false ;
for (int i = f ; i < S. size (); ++i) {
for (int x : S[i ]) {
if (w[x] == 0) ++c;
++w[x];
}
if ( set cover rec ( i+1, K−1, N, S, w, c )) return true;
for (int x : S[i ]) {
−−w[x];
if (w[x] == 0) −−c;
}
}
return false ;
}
(b) Let us see the function g defines a reduction from VERTEX-COVER to SET-COVER.
Clearly it takes polynomial time in the size of the input of VERTEX-COVER. It remains
to be seen that an input (K, G ) of VERTEX-COVER is positive if and only if g(K, G ) =
(K, N, S) is also positive for SET-COVER.
If (K, G ) is positive for VERTEX-COVER then there is a vertex cover W ⊆ V with |W | ≤
K. We define T = {Su | u ∈ W }. Then | T | ≤ K. Now let i be such that 0 ≤ i < N. Then the
edge ei = {u, v} satisfies that i ∈ Su , i ∈ Sv . Moreover, as W is a cover, u ∈ W or v ∈ W. If
u ∈ W then Su ∈ T and therefore we have a subset of T that includes i. The case v ∈ W is
analogous. Hence T is a subset cover of {0, . . . , N − 1}.
On the other hand, the function f does not define a correct reduction. For example,
suppose that K = 1 and G is the following graph:
u0 u1 u2
246 Solutions to Final Exams
Then the input (K, G ) is positive for VERTEX-COVER, as vertex u1 covers both edges.
But f (K, G ) = (1, 3, {{0, 1}, {1, 2}}) is not positive for SET-COVER, since there is no sin-
gle subset that covers {0, 1, 2}.