CHRISTIAN MWENDA GITONGA
23/06387
ASSIGNMENT 3
QUESTION 1
1. Algorithm efficiency is a key consideration in computer science, and Big O Notation
provides a framework to understand it. Define Big O Notation and explain its role in
analyzing algorithm efficiency.
Big O Notation is a mathematical notation that describes the upper bound of the complexity or
time efficiency of an algorithm. It provides a way of expressing the worst case scenario of an
algorithm’s performance as the input size grows larger.
It classifies algorithms based on how their running time grows as the input size increases. This
allows computer scientists and programmers to choose and compare the most efficient
algorithm for a given problem.
2. Analyze the time complexity of the following operations in terms of Big O:
o Accessing an element in an array – O(1) Constant time; It takes constant time
regardless of the size of the array.
o Inserting an element at the end of a singly linked list – O(n) Linear time; In singly
linked list there is no direct access to the last element therefore you must go throught
the entire list. O(n) in this case is the number of elements.
o Enqueuing in a circular queue – O(1) Constant time; Inserting an element at the end
takes constant time.
o Inserting into a binary search tree – O(h); It will depend on the height of the tree as
the insertion process involves iterating the tree from the root to find the right position
for the new element.
3. Describe a scenario where selecting a more efficient algorithm (in terms of Big O
Notation) could significantly impact a system’s performance. Provide a comparison
between a less efficient and a more efficient approach in your example.
In the field of web searching a more efficient algorithm could significantly impact a system’s
performance.
In a web search engine, a less efficient algorithm like linear search would have to check every
single webpage in the indexed database every time a query is submitted by the user this would
significantly slow down the search time and make the system less responsive.
A more efficient algorithm like binary search or hash function would improve the performance.
QUESTION 2
1. Sorting algorithms have different levels of efficiency and are chosen based on specific
requirements. Compare and contrast Bubble Sort, Quick Sort, and Merge Sort in terms
of time complexity, best use cases, and efficiency.
i. Bubble sort
Time complexity
Best case; O(n) when the list is already sorted.
Average case; O(n²) for unsorted lists.
Best use case
It is used for teaching sorting concepts because of its simplicity.
It is suitable for small datasets where the overhead of more efficient algorithms is not justified.
Efficiency
It is not adaptive
Inefficient for large datasets
ii. Quick Sort
Time complexity
Best case; O(n log n) when the pivot divides the list into nearly equal parts.
Worst case; O(n²) when the pivot selection is poor.
Best use case
It is used for large datasets as it is highly efficient.
Useful for situations where memory is limited as doesn’t require additional memory to store.
Efficiency
Might be slow for certain inputs but this can be mitigated by using techniques like median-of-
three pivot selection.
It is efficient for large datasets.
iii. Merge sort
Time complexity
O(n log n) because it always divides the array in half and requires merge step.
Best use case
Suitable for external sorting where data doesn’t fit into memory.
Efficiency
It is stable and preserves the relative order of equal elements.
It performs consistently as it guarantees the same time complexity in all cases.
2. Describe a situation where using Merge Sort would be more advantageous than Quick
Sort. Explain your reasoning with reference to the characteristics of each algorithm.
When the input is already sorted or nearly sorted.
Merge sort is a divide and conquer algorithm that takes a sequential list and divides it into
halves then divides each half again until each half contains only one element. The algorithm the
merges those two halves back together sorting out the data as it goes.
Quick sort relies on partitioning the list into two parts based on a pivot element. The algorithm
sorts each partition separately and combine the sorted partitions together.
3. Write pseudocode for Merge Sort and briefly explain each step .
MergeSort(arr):
if length of arr > 1:
mid = length of arr / 2
left_half = arr[0...mid-1]
right_half = arr[mid...end]
MergeSort(left_half) # Recursively sort the left half
MergeSort(right_half) # Recursively sort the right half