You are on page 1of 6

Exercise 1.

1
f is not a function because it does not satisfy the mathematical definition of a function, which states that for
every input, there can only be one output. In this case, for the input (3, 4, 4, 5), the output would be 1 and
2. Since the function maps the same input (4) to more than one output, it is not a function.

Exercise 1.2
If we require the lists we use to not have repeated elements, then f can be seen as a function because for
every input, there is only one output. This function is injective, because for every unique input, it produces
a unique output.

It is not surjective, because there is no guarantee that every element of the output set can be reached as
the output of this function.

Therefore, this function is an injective function but not surjective, hence it is not a bijective function, which
is a function that is both injective and surjective.

Exercise 2.1:
code

Exercise 2.2:
Linear Search:

List number Time(seconds) Exists?


500 0.9320000s Does not
1000 1.9560000s Does not
2000 3.9440000s Does not
4000 8.2020000s Does not
9000 16.7870000s Does not

Binary Search:

List number Time(seconds) Exists?


500 0.0360000s Does not
1000 0.0430000s Does not
2000 0.0440000s Does not
4000 0.0450000s Does not
9000 0.0540000s Does not
Exercise 2.3:

Figure 1: Linear search

Figure 2: Binary search

Linear with logarithmic

Exercise 3.1:
linear seaacghe linear search algorithm compares an input value to each element in a given array or list,
one at a time, until a match is found or the end of the array is reached. In the worst case, the input value
being searched for is not present in the array, and the algorithm must compare the input value to every
element in the array before determining that it is not present.
In this case, the number of comparisons made is directly proportional to the number of elements in the
array, n. Therefore, the worst-case number of comparisons made by the linear search algorithm is n + 1

In worst case, we need to compare the input with every element of the array. The first comparison will be
between input and first element of the array, second comparison will be between input and second
element of the array and so on. Finally, we need to compare the input with last element of the array. In
addition, we need one more comparison for checking if the input is not present in the array. Thus, 2n+2
comparisons will be made in worst case.

For example, if the input value is 5 and the array is [1, 2, 3, 4], the algorithm will make 4 comparisons (5 ==
1, 5 == 2, 5 == 3, 5 == 4) before determining that 5 is not present in the array.

Exercise 3.2:
Big Omega notation specifically describes average case scenario. It represents the most realistic time
complexity of an algorithm.

Θ(n) represents the upper and lower bounds of the algorithm's time complexity, where n is the size of the
input array. In the worst case, the input value is not present in the array, and the algorithm must compare
the input value to every element in the array before determining that it is not present. Therefore, the
number of comparisons made by the algorithm is directly proportional to the number of elements in the
array.

We can represent this mathematically as:

T (n)=2 n+2 comparisons, where T (n) is the time complexity of the algorithm and n is the size of the
input array.

This can be simplified as:

T (n)=2 n+2 comparisons ¿ n+1+1 comparisons


Since the constant 1 can be dropped as it does not affect the order of growth of the function and we are
interested in the upper bound of the function.

T (n)=n+1 comparisons ¿ Θ(n)


So, the number of comparisons made by the linear search algorithm in the worst case is in Θ(n) which
means that it grows linearly with the size of the input array.

Here, n+1 represents the number of comparisons made by the algorithm to check each element of the
array and 1 represents the comparison made to check if the input is not present in the array.

Therefore, both equations represent the same thing, the worst-case time complexity of the linear search
algorithm, which is Θ(n).
Exercise 3.3:
Every full iteration of the while loop in the binary search algorithm compares the middle element of a given
sublist to the target value. If the middle element is not the target value, the algorithm splits the sublist in
half and continues the search in one of the two resulting sublists, based on whether the target value is
greater or less than the middle element.

Since the algorithm performs two comparisons in each iteration, one to check if the middle element is the
target value and one to check if the target value is greater or less than the middle element, every full
iteration of the while loop uses two comparisons.

In the first iteration of the while loop, the algorithm starts by considering the entire list of length n=2 k .
n−1
The middle element of this list is the element at index . The middle element of this list is the element
2
2k −1 k−1 1
at index =2 − .
2 2
k
2 1 k−1 1
− =2 −
2 2 2
This means that in the first iteration of the while loop, m=2 k−1

After the first time the while loop has run, we have excluded half of the elements of the list. This is because
the algorithm splits the list in half, based on whether the target value is greater or less than the middle
element. Since the algorithm continues the search in one of the two resulting sublists, half of the original
list is excluded from further consideration.

To end up with a list of just one element, we have to half the list log 2 n times. This is because log 2 n
represents the number of times we need to divide n by 2 to get a value of 1. Since binary search algorithm
works by dividing the array into two parts each time, it needs log 2 n iterations to get to the element we are
searching for, assuming n is a power of 2. If n is not a power of 2, the algorithm will not divide the list into
two equal parts and it will take more steps to reach the target element.

Once i= j, the while loop checks its run condition once more, and then the algorithm continues to check if
we have found the element in question. After the while loop has run log 2 n times, there will be only one
element remaining in the list and the algorithm will check the remaining element with one comparison. In
total the algorithm will have used log 2 n iterations of the while loop, each using 2 comparisons and one
final comparison, giving us 2 · log 2 n+ 2 comparisons.

The times 2 comes from the fact that, in each iteration of the while loop, the algorithm performs two
comparisons. One comparison to check if the middle element is the target value and another comparison to
check if the target value is greater or less than the middle element.

The +2 comes from the fact that the algorithm performs one comparison to check if the target value is in
the array or not, and one comparison to check if the remaining element is the target value at the end of the
while loop

It's important to note that this assumes that n is a power of 2, if n is not a power of 2, the algorithm will not
divide the list into two equal parts and it will take more steps to reach the target element, so the number of
comparisons may be different.
Exercise 3.4:
The number of comparisons needed for the binary search algorithm can be represented using the
mathematical notation Θ(log_2(n)), where n is the size of the input array.

The upper bound of the number of comparisons made by the binary search algorithm is 2 · log 2 n+ 2, which
is the number of comparisons made in the worst-case scenario, where the target value is not in the array.

The lower bound of the number of comparisons made by the binary search algorithm is log 2 n, which is the
number of comparisons made in the best-case scenario, where the target value is the middle element of
the array.

So, we can say that the number of comparisons made by the binary search algorithm is Θ(log 2 n) which
means that the number of comparisons grows logarithmically with the size of the input array, and it is on
average log 2 n.

It's worth noting that this assumes that n is a power of 2, if n is not a power of 2, the algorithm will not
divide the list into two equal parts and it will take more steps to reach the target element.

Exercise 3.5:
The theoretical results and the results from your implementation for linear search show a similar trend. The
time taken to perform the linear search increases linearly with the size of the input array, which is
consistent with the worst-case time complexity of O(n) for the linear search algorithm.

The theoretical results and the results from your implementation for binary search also show a similar
trend. The time taken to perform the binary search remains relatively constant, even as the size of the
input array increases, which is consistent with the average case time complexity of Θ(log 2 n) for the binary
search algorithm. The time taken is much smaller than the linear search, which is also in line with the
theoretical results.

Overall, the results from the implementation are consistent with the theoretical results and support the
claim that binary search algorithm is more efficient than linear search algorithm in terms of time
complexity.

Exercise 3.6:
When we search for m elements using linear search, the number of comparisons used will be m·n , where n
is the number of elements in the list. In this case, with a list of 10000 elements, we would use
4
m·10000=m·10 comparisons.

A list of n elements can be sorted with an effort of Θ(n· log 2 n), which means that the number of
operations needed to sort the list is n· log 2 n. In this case, with a list of 10000 elements, we would use
10000 log 2 10000=10000 ·13.3=133000 operations. Once the list is sorted, we would search for m
elements using binary search, which would take m∗log 2 n comparisons. In this case, it would take
m∗log2 10000=m·13.3 comparisons.

The point at which the two approaches have similar complexity is when the number of comparisons for
linear search (m· n) is equal to the number of comparisons for binary search ( m· log 2 n+ n· log 2 n ).

n
First, we can divide both sides of the equation by m: n=log 2 n+ · log 2 n
m
Now we can see that n=log 2 n∗(1+n /m)

We know that log 2 n is a constant value, and it will not change with m, so we can say that n=log 2 n∗C
where C=1+n /m

So we have n=log 2 n∗C

Dividing both sides by log 2 nwe get:

n
=C
log 2 n

Now we can see that


n
log 2 n
=n·
(1
log 2 n )
1 n 1
We know that is a constant value, so we can say that =n·K where K=
log 2 n log 2 n log 2 n

Finally, we get m=n·K=n· ( 1


log2 n )
=n· log 2 n So m=n log 2 n

So the point at which the two approaches have similar complexity is when m=n· log 2 n.

When m is less than n log 2 n, the binary search approach is better, as it has a lower time complexity of O(
log 2 n), while linear search has a time complexity of O(n). When m is greater than n· log2 n, the linear
search approach is better, as it has a lower time complexity of O(m) while binary search has a time
complexity of O(m· log 2 n ), which is greater than O(m).

In this case, with a list of 10000 elements and searching for m elements, for
m<10000 log 2 10000=10000 ·13.3=133000, the binary search approach is better, as it has a lower time
complexity. However, for m>10000 log 2 10000=10000 ·13.3=133000, the linear search approach is
better, as it has a lower time complexity.

You might also like