csc3323_algorithmanalysisexercises
DESCRIPTION
Series of exercises, time complexity and number of iterations (sigma & big Oh notation), recursive relations solving, graph theory (topological sort, shortest path ...)TRANSCRIPT
CSC 3323 - Algorithm Analysis
Practicing problems
Mohamed Ennahdi El Idrissi
Summer 2012
1)
a. For the following fragments, give the exact number of iterations and the time complexity:
sum = 0;
for ( i = 0 ; i < n ; i ++) {
sum ++;
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i ++) {
for ( j = 0 ; j < n ; j ++) {
sum ++;
}
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i ++) {
for ( j = 0 ; j < n * n ; j ++) {
sum ++;
}
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i ++) {
sum ++;
}
for ( j = 0 ; j < n * n ; j ++) {
sum ++;
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i += 2 ) {
sum ++;
}
for ( j = 0 ; j < n * n ; j ++ ) {
sum ++;
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i ++) {
for ( j = 0 ; j < i ; j ++) {
sum ++;
}
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i ++ ) {
for ( j = 0 ; j < n * n ; j ++ ) {
for ( k = 0 ; k < n ; k ++ ) {
sum ++;
}
}
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; 2 * i < n ; i ++ ) {
sum ++;
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = n ; i > 0 ; i -- ) {
sum ++;
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 1 ; i < n ; i = i * 2 ) {
sum ++;
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 1 ; i * i <= n ; i ++ ) {
for ( j = 1 ; j <= i ; j = j * 2 ) {
sum ++;
}
}
--------------------------------------------------------------------------------------------------------------------------------------
b. The following code fragments afford an amelioration that would affect positively the
performances. Where can you apply this amelioration?
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i ++) {
for ( j = 0 ; j < n * n ; j ++) {
sum ++;
}
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i ++) {
sum ++;
}
for ( j = 0 ; j < n * n ; j ++) {
sum ++;
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i += 2 ) {
sum ++;
}
for ( j = 0 ; j < n * n ; j ++ ) {
sum ++;
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; i < n ; i ++ ) {
for ( j = 0 ; j < n * n ; j ++ ) {
for ( k = 0 ; k < n ; k ++ ) {
sum ++;
}
}
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 0 ; 2 * i < n ; i ++ ) {
sum ++;
}
--------------------------------------------------------------------------------------------------------------------------------------
sum = 0;
for ( i = 1 ; i * i <= n ; i ++ ) {
for ( j = 1 ; j <= i ; j = j * 2 ) {
sum ++;
}
}
--------------------------------------------------------------------------------------------------------------------------------------
2) Resolve the following recursion relations and find their time complexity:
a. T(n) = T(n - 1) + c
b. T(n) = T(n – 1) + nc
c. T(n) = T(n / 2) + c
d. T(n) = 2T(n/2) + cn
e. T(n) = 2T(n - 1) + c
f. T(n) = 3T(n/2) + cn2
g. T(n) = 2T(n/2) + cn log n
h. T(n) = T(n - 2) + c
i. T(n) = T(n - 1) + T(n - 2) + c
j. T(n) = 3T(n / 3) + cn
k. T(n) = 2T(n / 2) + n / log n
l. T(n) = 2T(n - 1) + c
m. T(n) = 4T(n/2) + n² log2 n
n. T(n) = T(√n) + c
o. T(n) = 2T(√n) + log2 n
p. T(n) = 2 i=0∑n - 1 T(i) + 1
q. T(n) = 1/n i=0∑n - 1 T(i) + n
r. T(n) = 2/n i=0∑n - 1 T(i) + n
r. T(n) = i=0∑n - 1 i *
T(i) + n
3) Graph theory: Topological Sort
a. This graph illustrates a sample of the courses offered by AUI's Computer
Science department. Apply the topological sort on this graph (show steps).
b. Why is it possible to use topological sort on this graph?
4. Graph Theory: DFS, BFS, MST, Shortest Path
Use DFS (a) and BFS (b) to traverse the graph thoroughly, with the constraint of
visiting the cities only once (show the steps).
MST: A telecommunication company would like to establish a wired network.
- using both Prim's (c) and Kruskal (d), show the steps of connecting all
the cities (vertices) of the graph below.
Shortest Path: using Dijkstra (e), Bellman-Ford (f), and Floyd (g), find the
shortest path, knowing that the starting point is Agadir, and the destination is
Oujda.
Solutions:
When a loop increment is addition/subtraction, the formula to apply is:
(n - k) / m
where
for ( i = k ; i < n ; i += m );
sum = 0; for ( i = 0 ; i < n ; i ++) { for ( j = 0 ; j < n ; j ++) { sum ++; } }
Outer loop: (N - 0) / 1 = N Inner loop: (N - 0) / 1 = N Therefore the running time is:
N * N -> O(N²)
sum = 0; for ( i = 0 ; i < n ; i ++) { for ( j = 0 ; j < n * n ; j ++) { sum ++; } }
Outer loop: (N - 0) / 1 = N Inner loop (N * N - 0) / 1 = N² Therefore, the running time is:
N * N² = O(N3)
sum = 0; for ( i = 0 ; i < n ; i ++) { sum ++; }
Applying the formula above, we get: (N - 0) / 1 = N, Therefore the running time is:
O(N)
sum = 0; for ( i = 0 ; i < n ; i ++) { sum ++; } for ( j = 0 ; j < n * n ; j ++) { sum ++; }
First loop: (N - 0) / 1 = N Second loop: (N * N - 0) / 1 = N² Therefore, the running time is:
O(N) + O(N²) = O(N²)
sum = 0; for ( i = 0 ; i < n ; i += 2 ) { sum ++; } for ( j = 0 ; j < n * n ; j ++ ) { sum ++; }
First loop: (N - 0) / 2 = N / 2 Second loop: (N * N - 0) / 1 = N² Therefore, the running time is:
O(N) + O(N²) = O(N²)
For nested loops, which indexes depend on the index of the immediately outer loop, the formula is as the following:
n ( n + 1 ) ( n + 2 ) ... ( n + r - 1 ) / r! =
Where c is the number of operations, n is the number of elements, and r is the number of nested loops.
sum = 0; for ( i = 0 ; i < n ; i ++ ) { for ( j = 0 ; j < n * n ; j ++ ) { for ( k = 0 ; k < n ; k ++ ) { sum ++; } } }
Outermost loop: (N - 0) / 1 = N First inner loop: (N * N - 0) / 1 -> N² Innermost loop: (N - 0) / 1 = N Therefore, the running time is
O(N * N² * N) = O(N4)
sum = 0; for ( i = 0 ; 2 * i < n ; i ++ ) { sum ++; }
We have 2 * i < N = i < N / 2
Therefore, ((N / 2) - 0) / 1 = N / 2
This loop will iterate N / 2 times.
O(N)
sum = 0; for ( i = 0 ; i < n ; i ++) { for ( j = 0 ; j < i ; j ++) { sum ++; } }
Since the nested loop depends on the index of the outer loop:
We have n, the number of, elements and r is the number of nested loops:
Therefore, the exact number of iterations would be:
n ( n + 1 ) / 2! = ( n² - n ) / 2 therefore, the running time is:
O(N²)
When a loop increment is multiplication/division, the formula to apply is:
(Logm (n / k) )
where
for ( i = k ; i < n ; i *= m );
sum = 0; for ( i = 1 ; i < n ; i = i * 2 ) { sum ++; }
(Log2 (n / 1)) -> (Log2 n)
When n = 8,
the loop will iterate Log2 23 = 3 times.
When n = 10,
the loop will iterate Log2 10 = 3.3219280949
-> 4 times.
sum = 0; for ( i = 1 ; i * i <= n ; i ++ ) { for ( j = 1 ; j <= i ; j = j * 2 ) { sum ++; } }
Outer loop:
We have i * i < N -> i < √N
(√N - 1) / 1 -> √N - 1
Inner loop:
(Log2 (i / 1)) -> (Log2 i).
For the inner loop, we notice that
its number of iterations depend on
i:
When i = 1, Log 1 -> 0 iterations;
When i = 2, Log 2 -> 1 iteration;
When i = 3, Log 3 -> 1 iteration;
...
When i = √N, Log2 √N
And we know that:
i=1∑N log i = N Log N Since we are dealing with √N instead
of N, the time complexity is:
O(√N Log N)
2.
sum = 0; for ( i = n ; i > 0 ; i --) { sum ++; }
Applying the formula above, we get: (0 - N) / -1 = N, Therefore the running time is:
O(N)
a. T(n) = T(n - 1) + c
T(n) = (T(n - 2) + c) + c
T(n) = ((T(n - 3) + c) + c) + c
T(n) = T(n - 3) + 3c
...
T(n) = T(n - k) + kc
when n - k = 0 -> n = k, and T(0) = 1
T(n) = T(0) + nc
Therefore, the time complexity is O(N) b.
T(n) = T(n – 1) + nc
T(n) = (T(n - 2) + (n - 1)c) + nc
T(n) = ((T(n - 3) + (n - 2)c) + (n - 1)c) + nc
T(n) = T(n - 3) + cn - 2c + cn - c + nc
T(n) = T(n - 3) + 3cn - 2c - 1c - 0c
...
T(n) = T(n - k) + kcn - c(i = 0∑k - 1
i)
T(n) = T(n - k) + kcn - c( (k - 1)(k) / 2 )
T(n) = T(n - k) + kcn - ck² / 2 - ck / 2
when n - k = 0 -> n = k, and we have T(0) = 1
T(n) = T(0) + cn² - cn² / 2 - cn / 2
T(n) = T(0) + cn² / 2 - cn / 2
Therefore, time complexity is O(N²).
c. T(n) = T(n / 2) + c
T(n) = (T(n / 2²) + c) + c
T(n) = ((T(n / 23) + c) + c) + c
...
T(n) = T(n / 2k) + kc
when n / 2k = 1, n = 2
k then k = log2 n
T(n) = T(1) + c log2 n
Therefore the time complexity is O(log2 n).
d. T(n) = 2T(n/2) + cn
T(n) = 2(2T(n/2²) + cn/2) + cn
T(n) = 2(2(2T(n/23) + cn/2²) + cn/2) + cn
T(n) = 23 T(n/2
3) + 2²cn/2² + 2cn / 2 + cn
...
T(n) = 2k T(n/2
k) + kcn
when n / 2k = 1, n = 2
k so k = log2 n
T(n) = 2log n
T(1) + c n log2 n
Therefore, the time complexity is O(N Log N) e. T(n) = 2T(n - 1) + c
T(n) = 2(2T(n - 2) + c) + c
T(n) = 2(2(2T(n - 3) + c) + c) + c
T(n) = 23T(n - 3) + 3c
...
T(n) = 2kT(n - k) + kc
when n - k = 0, n = k
T(n) = 2nT(0) + nc The time complexity is O(2n) (Non polynomial -> Algorithm to be discarded).
f. T(n) = 3T(n/2) + cn2
T(n) = 3(3T(n/22) + cn
2 / 2) + cn²
T(n) = 3(3(3T(n/23) + cn
2 / 2²) + cn² / 2 + cn²
T(n) = 33T(n/2
3) + 3²cn
2 / 2² + 3
1cn² / 2 + 3
0 cn² / 2
0
...
T(n) = 3kT(n/2
k) + 3
k-1cn
2 / 2
k-1 + 3
k-2cn² / 2
k-2 ... + 3
0 cn² / 2
0
T(n) = 3kT(n/2
k) + cn
2 i=0∑k-1
3i/2
i
when n/2k = 1, n = 2
k -> k = log2 n
T(n) = 3log n
+ cn2 (i=0∑((log n) - 1)
3i/2
i) <=
3log n
+ cn2 i=0∑
∞ 3i/2
i
T(n) <= Θ(3log n) + cn2 [1 / (1 - 3/2)]
T(n) <= Θ(nlog 3) + O(n2)
The time complexity is O(n²).
The formula of i=0∑k-1 3i/2i [i=0∑k-1 (3/2)i] was found through the demonstration below:
Thus
Refer to the Zeno Summation.
g. T(n) = 2T(n/2) + cn log n
T(n) = 2(2T(n/2²) + cn/2 log n/2) + cn log n
T(n) = 2(2(2T(n/23) + cn/2² log n/2²) + cn/2 log n/2) + cn log n
T(n) = 23T(n/2
3) + c2
²n/2² log n/2² + c2
1n/2
1 log n/2
1 + c2
0n/2
0 log n/2
0
T(n) = 23T(n/2
3) + cn log n/2² + cn log n/2
1 + cn log n/2
0
...
T(n) = 2kT(n/2
k) + cn (i=0∑k-1
log n/2i)
when n/2k = 1, k = log2 n
T(n) = 2log n
T(1) + cn (i=0∑(log n) - 1 log n/2
i)
i=0∑(log n) - 1 log n/2
i) = i=0∑(log n) - log 2
log n/2i)
i=0∑(log n) - 1 log n/2
i) = i=0∑(log n/2)
log n/2i)
T(n) = Θ(n) + cn (i=0∑(log n/2) log n - log 2
i)
we have log 2i = i log 2 = i
T(n) = Θ(n) + cn (i=0∑(log n/2) (log n) - i)
i=0∑(log n/2) (log n) - i = i=0∑(log n/2)
(log n) - i=0∑(log n/2) i
= log2 n/2 * log2 n - [(log2 n/2) * (log2 n/2 + 1) / 2] = (log2 n - 1) log n - [(log2 n - 1) (log2 n - 1 + 1)/2] = (log2 n - 1) log2 n - [(log2 n - 1) (log2 n)/2] = log2² n - log2 n - 1/2log2² n + 1/2log2 n = 1/2log2² n - 1/2log2 n
= 1/2 (log2 n - 1) log2 n
T(n) = Θ(n) + cn (1/2 (log2 n - 1) log2 n)
T(n) = Θ(n) + cn Θ(log2² (n))
Therefore, the time complexity is Θ(n log2² n)
h. T(n) = T(n - 2) + c
T(n) = (T(n - 4) + c) + c
T(n) = ((T(n - 6) + c)) + c) + c
T(n) = T(n - 6) + 3c
...
T(n) = T(n - k) + ck/2
when n - k = 0 -> n = k
T(n) = T(0) + cn/2
T(n) = 1 + cn/2
Therefore, the time complexity is Θ(n)
i. T(n) = T(n - 1) + T(n - 2) + c
we consider the following:
T(n - 2) + T(n - 2) <= T(n - 1) + T(n - 2) <= T(n - 1) + T(n - 1)
Ω(X) | Θ(Y)
| O(Z)
Lower bound upper bound
Ω(X):
T(n) >= 2T(n - 2) + c T(n) >= 2(2T(n - 4) + c) + c T(n) >= 2(2(2T(n - 6) + c) + c) + c T(n) >= 2
3T(n - 6) + 2
2c + 2
1c + 2
0c
... T(n) >= 2
kT(n - (2*k)) + 2
k-1c + 2
k-2c + ... + 2
0c
T(n) >= 2kT(n - (2*k)) + i=0∑k-1
c
When n - 2*k = 0 -> n = 2k -> k = n/2
T(n) >= 2n/2T(0) + i=0∑(n/2)-1
c
T(n) >= 2n/2
+ cn/2
Therefore, the time complexity for this case: Ω(2n)
O(Z):
T(n) <= 2T(n - 1) + c T(n) <= 2(2T(n - 2) + c) + c T(n) <= 2(2(2T(n - 3) + c) + c) + c T(n) <= 2
3T(n - 3) + 2
2c + 2
1c + 2
0c
...
T(n) <= 2kT(n - k) + i=0∑k-1
c
When n - k = 0 -> n = k
T(n) <= 2nT(0) + i=0∑n-1
c
T(n) <= 2n + cn
Therefore, the time complexity for this case: O(2n)
Since Ω(2n) = O(2
n) -> The time complexity is Θ(2n).
k. T(n) = 2T(n/2) + n / log2 n
T(n) = 2(2T(n/22) + n / 2 / log2 n / 2) + n / log2 n
T(n) = 2(2(2T(n/23) + n/2
2 / log2 n / 2
2) + n / 2 / log2 n / 2) + n / log2 n
T(n) = 23T(n/2
3) + 2
2n/2
2/log2 n/2
2 + 2
1n/2
1/log2 n/2
1 + 2
0n/2
0 / log2 n/2
0
T(n) = 23T(n/2
3) + n/log2 n/2
2 + n/log2 n/2
1 + n / log2 n
T(n) = 23T(n/2
3) + n/(log2 n - log2 2
2) + n/(log2 n / log 2) + n / log2 n
...
T(n) = 2kT(n/2
k) + n/(log2 n-log2 2
k-1) + n/(log2 n-log 2
k-2) ...
+ n / log2 n - 0
T(n) = 2kT(n/2
k) + n/(log2 n- k - 1) + n/(log2 n- k - 2)
... + n / log2 n - 0
T(n) = 2kT(n/2
k) + i=0∑(k - 1)
n / ((log2 n) - i)
when n/2k = 1, k = log2 n
T(n) = 2log n
T(1) + i=0∑log n/2 n / ((log2 n) - i)
T(n) ≈ Θ(n) + n j=1∑log n 1 / j
T(n) ≈ Θ(n) + n log2 log2 n
The time complexity is Θ(n log2 log2 n).
why i=0∑log n/2 n / ((log2 n) - i) ≈ n j=1∑log n 1 / j ?
Assume that n = 8, log2 8 = 3, we thus would have 2 iterations ((log2 8) - 1).
i=0∑(log 8/2) n / ((log2 8) - i) =
when i = 0, 8 / (log2 23 - 0) = 8 / 3
when i = 1, 8 / (log2 23 - 1) = 8 / 2
when i = 2, 8 / (log2 23 - 2) = 8 / 1;
i=0∑(log 8/2) n / ((log2 8) - i) = 8 / 3 + 8 / 2 + 8 / 1;
8 * (j=1∑log 8 1 / j) =
when j = 1, 1 / 1 = 1 / 1
when j = 2, 1 / 2 = 1 / 2
when j = 3, 1 / 2 = 1 / 3
8 * j=1∑log 8 1 / j = 8 (1/1 + 1/2 + 1/3) = 8/1 + 8/2 + 8/3
Hence, i=0∑log n/2 n / ((log2 n) - i) ≈ n(j=1∑log n 1 / j).
When n is not a power of 2 (because, in our case, the logarithm is of base 2), the first series yields a value that is greater than the second series. For instance, when n = 1023,
i=0∑log 1023 - 1 1023 / ((log2 1023) - i) = 1023.00/9.9986 + 1023.00/8.9986 + 1023.00/7.9986 + 1023.00/6.9986 + 1023.00/5.9986 + 1023.00/4.9986 + 1023.00/3.9986 + 1023.00/2.9986 + 1023.00/1.9986 + 1023.00/0.9986.
i=0∑log 1023 - 1 1023 / ((log2 1023) - i) = 102.3144 + 113.6845 + 127.8975 + 146.1723 + 170.5401 + 204.6577 + 255.8402 + 341.1603 + 511.8608 + 1024.4440.
i=0∑log 1023 - 1 1023 / ((log2 1023) - i) = 2998.58
1023(j=1∑log 1023 1 / j) = 1023/1 + 1023/2 + 1023/3 + 1023/4 + 1023/5 + 1023/6 + 1023/7 + 1023/8 + 1023 / 9 + 1023 / 10.
1023(j=1∑log 1023 1 / j) = 1023.0000 + 511.5000 + 341.0000 + 255.7500 + 204.6000 + 170.5000 + 146.1429 + 127.8750 + 113.6667 + 102.3000.
1023(j=1∑log 1023 1 / j) = 2996.33.
The table below displays the values of the series 1 and the series 2 parallelly when n = 1023.
iteration 1/10 2/9 3/8 4/7 5/6 6/5 7/4 8/3 9/2 10/1 Series 1 102.3144 113.6845 127.8975 146.1723 170.5401 204.6577 255.8402 341.1603 511.8608 1024.4440 Series 2 102.3000 113.6667 127.8750 146.1429 170.5000 204.6000 255.7500 341.0000 511.5000 1023.0000
We notice above that all the values of the first series are larger than the second one.
The table below displays the values of the series 1 and the series 2 parallelly when n = 1025.
Iteration(i/j) 1/10 2/9 3/8 4/7 5/6 6/5 7/4 8/3 9/2 10/1 Series 1 102.4856 113.8711 128.1025 146.3991 170.7932 204.9423 256.1598 341.5064 512.1394 1023.5586 Series 2 102.5000 113.8889 127.1250 146.4286 170.8333 205.0000 256.2500 341.6667 512.5000 1025.0000
Here, we notice that all the values of the second series are larger than the first one.
Conclusion:
i=0∑log n/2 n / ((log2 n) - i) = n j=1∑log n 1 / j, when n is a power of 2.
i=0∑log n/2 n / ((log2 n) - i) >= n j=1∑log n 1 / j, when n smaller than the nearest
value that is a power of 2 (for instance: 1023, 2047 ...).
i=0∑log n/2 n / ((log2 n) - i) <= n j=1∑log n 1 / j, when n larger than the nearest
value that is a power of 2 (for instance: 1025, 2049 ...).
l. T(n) = 2T(n - 1) + c T(n) = 2(2T(n - 2) + c) + c T(n) = 2(2(2T(n - 3) + c) + c) + c T(n) = 2
3T(n - 3) + 2
2c + 2
1c + 2
0c
... T(n) = 2
kT(n - k) + 2
k-1c + 2
k-2c + ... + 2
0c
T(n) = 2kT(n - k) + i=0∑k - 1
2i
when n - k = 0, n = k and T(0) = 1
T(n) = 2nT(0) + i=0∑n - 1
2i
T(n) = Θ(2n) + 2
n - 1
T(n) = 2n+1 - 1 = Θ(2
n) - 1
Therefore, the time complexity is Θ(2n). (Non polynomial)
m. T(n) = 4T(n/2) + n² log2 n
T(n) = 4( 4T(n/2²) + n²/2 log2 n/2 ) + n² log2 n T(n) = 4( 4(4T(n/2
3) + n²/2² log2 n/2²) + n²/2 log2 n/2 ) + n² log2 n
T(n) = 43T(n/2
3) + 2²n²/2² log2 n/2² + 2n²/2 log2 n/2 + n² log2 n
T(n) = 43T(n/2
3) + 3 n² log2 n
... T(n) = 4
kT(n/2
k) + kn²log2 n
when n/2k = 1 -> k = log2 n, and we know that 4
log n = 2²
log n -> 4
log n = n²
T(n) = n²T(1) + kn²log2 n T(n) = Θ(n²) + n² log2 n log2 n T(n) = Θ(n²) + n² log2
2 n.
Therefore, the time complexity is Θ(n² log22 n ).
n. T(n) = T(√n) + c = T(n) = T(n1/2) + c
T(n) = (T(n1/4) + c) + c
T(n) = ((T(n1/8) + c) + c) + c = T(n) = T(n
1/8) + 3c
T(n) = T(n^1/2k) + kc
We have n^1/2k = 2, and let's assume that X = 1/2
k
nX = 2, n = 2
1/X -> n = 2^2
k -> log2 n = 2
k.
Now let's assume that Y = log2 n:
Y = 2k -> k = log2 Y which means that k = log2 log2 n = log2
2 n.
Hence, T(n) = T(2) + c log22 n.
Therefore, the time complexity is Θ(log22 n).
o. T(n) = 2T(√n) + log2 n = T(n) = 2T(n1/2) + log2 n
T(n) = 2(2T(n1/4) + log2 n
1/2) + log2 n
T(n) = 2(2(2T(n1/8) + log2 n
1/4) + log2 n
1/2) + log2 n
T(n) = 23T(n^1/2
3) + 2
2log2 n^1/2² + 2
1log2 n
1/2 + log2 n
T(n) = 23T(n^1/2
3) + 2
2 * 1/2²
log2 n + 2
1 * 1/2
log2 n + log2 n
T(n) = 23T(n^1/2
3) + 3 log2 n
...
T(n) = 2kT(n^1/2
k) + k log2 n
T(n) = 2kT(n^1/2
k) + k log2 n
We have n^1/2k = 2, and let's assume that X = 1/2
k:
nX = 2 -> n = 2
1/X -> n = 2^2
k -> log2 n = 2
k -> k = log2 log2 n
T(n) = 2log log n
T(2) + log2 n log2 log2 n
T(n) = Θ(log2 n) + Θ(log2 n log2 log2 n).
Therefore, the time complexity is: Θ(log2 n log2 log2 n)
4.a Topological Sort
Initial Graph
CSC 1401 had no in-edges.
CSC 1401 is the first element to be selected, and therefore eliminated with its out-edges.
this time, CSC 2302 is the next selected element.
So far, the topological sort result is: CSC 1401 -> CSC 2302
For the next element, we can choose CSC 2303, CSC 2304, or CSC 3324 to pursue the process. We opt for CSC 2303, hence we notice that
three vertices have no edges, those are going to be included in the topological sort list in the next step.
The list so far is: CSC 1401 -> CSC 2302 -> CSC 2303
Getting rid of the three vertices that have no in or out edges: CSC 1401 -> CSC 2302 -> CSC 2303 -> 3315 -> 3323 -> 3309
Getting rid of the three vertices that have no in or out edges:
CSC 1401 -> CSC 2302 -> CSC 2303 -> 3315 -> 3323 -> 3309 -> 2304
CSC 1401 -> CSC 2302 -> CSC 2303 -> 3315 -> 3323 -> 3309 -> 2304 -> CSC 3351
CSC 1401 –> CSC 2302 –> CSC 2303 –> CSC 3315 –> CSC 3323 –> CSC 3309 –> CSC 3352 -> CSC 2304 –> CSC 3351 –> CSC 5304 –> CSC 5339
CSC 1401 –> CSC 2302 –> CSC 2303 –> CSC 3315 –> CSC 3323 –> CSC 3309 –> CSC 3352 -> CSC 2304 –> CSC 3351 –> CSC 5304 –> CSC 5339 ->
CSC 3324 -> CSC 5338
CSC 1401 –> CSC 2302 –> CSC 2303 –> CSC 3315 –> CSC 3323 –> CSC 3309 –> CSC 3352 -> CSC 2304 –> CSC 3351 –> CSC 5304 –> CSC 5339 ->
CSC 3324 -> CSC 5338 -> CSC 3326 -> CSC 5301
CSC 1401 –> CSC 2302 –> CSC 2303 –> CSC 3315 –> CSC 3323 –> CSC 3309 –> CSC 3352 -> CSC 2304 –> CSC 3351 –> CSC 5304 –> CSC 5339 -> CSC 3324 -> CSC 5338 -> CSC 3326 -> CSC 5301 -> CSC 3325 ->
CSC 3327
CSC 1401 –> CSC 2302 –> CSC 2303 –> CSC 3315 –> CSC 3323 –> CSC 3309 –> CSC 3352 -> CSC 2304 –> CSC 3351 –> CSC 5304 –> CSC 5339 -> CSC 3324 -> CSC 5338 -> CSC 3326 -> CSC 5301 -> CSC 3325 ->
CSC 3327 -> CSC 3353
CSC 1401 –> CSC 2302 –> CSC 2303 –> CSC 3315 –> CSC 3323 –> CSC 3309 –> CSC 3352 -> CSC 2304 –> CSC 3351 –> CSC 5304 –> CSC 5339 -> CSC 3324 -> CSC 5338 -> CSC 3326 -> CSC 5301 -> CSC 3325 ->
CSC 3327 -> CSC 3353 -> CSC 5366
CSC 1401 –> CSC 2302 –> CSC 2303 –> CSC 3315 –> CSC 3323 –> CSC 3309 –> CSC 3352 -> CSC 2304 –> CSC 3351 –> CSC 5304 –> CSC 5339 -> CSC 3324 -> CSC 5338 -> CSC 3326 -> CSC 5301 -> CSC 3325 ->
CSC 3327 -> CSC 3353 -> CSC 5366 -> CSC 5365
The final result is:
CSC 1401 –> CSC 2302 –> CSC 2303 –> CSC 3315 –> CSC 3323 –> CSC 3309 –> CSC 3352 -> CSC 2304 –> CSC 3351 –> CSC 5304 –> CSC 5339 -> CSC 3324 -> CSC 5338 -> CSC 3326 -> CSC 5301 -> CSC 3325 -> CSC 3327 -> CSC 3353 -> CSC 5366 -> CSC 5365 -> CSC 5368 ->
CSC 5378
This result is one among many other results. Once more than one vertex has no in-edge, we can choose a vertex arbitrarily and come
up with an ordering. Any choice is correct.
4.b Topological sort is applicable for this graph, because it is a
Directed Acyclic Graph (DAG).
Dijsktra Shortest Path
Agadir Safi Marrakech Ouarzazate Settat Beni Mellal Casablanca Khouribga Errachidia Rabat Meknes Azrou Midelt Larache Fez Taza Oujda
0 ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞
● 292Agadir 249Agadir 364Agadir ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞
● 292Agadir ● 364Agadir 417Marrakech 444Marrakech ∞ 453Marrakech ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞
● ● ● 364Agadir 417Marrakech 444Marrakech 537Safi 453Marrakech ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞
● ● ● ● 417Marrakech 444Marrakech 537Safi 453Marrakech 663Ouarzazate ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞
● ● ● ● ● 444Marrakech 485Settat 453Marrakech 663Ouarzazate ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞
● ● ● ● ● ● 485Settat 453Marrakech 663Ouarzazate ∞
∞ ∞ ∞ ∞ ∞ ∞
● ● ● ● ● ● 485Settat ● 663Ouarzazate ∞ 695Khouribga ∞ ∞ ∞ ∞ ∞ ∞
● ● ● ● ● ● ● ● 663Ouarzazate 578Casablanca 695Khouribga ∞ ∞ ∞ ∞ ∞ ∞
● ● ● ● ● ● ● ● 663Ouarzazate ● 695Khouribga ∞ ∞ 745Rabat ∞ ∞ ∞
● ● ● ● ● ● ● ● ● ● 695Khouribga ∞ 804Errachidia 745Rabat ∞ ∞ 1193Errachidia
● ● ● ● ● ● ● ● ● ● ● 765Meknes 804Errachidia 745Rabat 755Meknes ∞ 1193Errachidia
● ● ● ● ● ● ● ● ● ● ● 765Meknes 804Errachidia ● 755Meknes 1096Larache 1193Errachidia
● ● ● ● ● ● ● ● ● ● ● 765Meknes 804Errachidia ● ● 928Fez 1193Errachidia
● ● ● ● ● ● ● ● ● ● ● ● 804Errachidia ● ● 928Fez 1193Errachidia
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 928Fez 1193Errachidia
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 1193Errachidia
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●
Therefore, we notice that, through backtracking starting from the destination (Oujda), the shortest path is: Oujda -> Errachidia -> Ouarzazate -> Agadir The red weights suggest that a shorter path was found from a different vertex.
References
- http://faculty.kfupm.edu.sa/ics/jauhar/ics202/Unit03_ComplexityAnalysis1.ppt
- http://faculty.kfupm.edu.sa/ics/jauhar/ics202/Unit03_ComplexityAnalysis2.ppt
-http://faculty.kfupm.edu.sa/ics/jauhar/ics202/Unit12_AnalysisOfRecursiveAlgorithms.ppt
- Data Structures and Algorithm Analysis, 3rd edition - Mark Allen Weiss
- http://people.csail.mit.edu/thies/6.046-web/master.pdf
- http://www.cse.unr.edu/~bebis/CS477/Lect/Recurrences.ppt
- http://www.cs.uiuc.edu/class/fa08/cs473/Lectures/lecture3.pdf
- http://www.cs.uccs.edu/~jkalita/algorithms.pdf