Assignment -1
Name – Mahamudul Hassan
Id – 2121048042
Course – CSE373
Section – 11
Serial No -11
## Answer : Algorithm Implementation
🔹 Constant Time – O(1)
In constant time complexity, the algorithm performs a fixed number of
operations regardless of the input size.
Example: Accessing an element from an array by its index.
🔹 Linear Time – O(n)
In linear time complexity, the algorithm’s execution time increases
proportionally with the input size.
Example: Searching for a specific value by iterating through the entire array.
🔹 Quadratic Time – O(n²)
Quadratic time complexity typically arises from algorithms that use nested
loops over the input.
Example: Comparing every pair of elements in an array to count duplicates.
🔹 Logarithmic Time – O(log n)
Logarithmic time complexity appears when the problem size is reduced by
half with each step.
Example: Binary search in a sorted array.
🔹 Linearithmic Time – O(n log n)
Linearithmic time complexity is common in efficient divide-and-conquer
algorithms.
Example: Sorting an unsorted array using Merge Sort or Quick Sort.
Answer - Graph
Answer – Excel shit
Assignment Answer (Summary)
2. Measuring Execution Time
The Python time module was used. For each function, the timer started
before and stopped after the function call. The difference (end - start) gave
the execution time for each input size.
3. Testing Different Input Sizes
Algorithms were tested with input arrays of size 10 to 10,000 (random
integers from -1000 to 1000). The quadratic algorithm (O(n²)) was only
tested up to size 1,000 to avoid long runtimes.
4. Saving & Visualizing Results
Execution times were saved to execution_times.csv using pandas. A graph
was plotted with matplotlib to show how time grows with input size for each
algorithm.
5. Analysis & Trends
O(1) stays constant.
O(n) grows linearly.
O(n²) grows very fast.
O(log n) grows very slowly.
O(n log n) grows moderately.
Code Summary
The code implements, tests, records, and plots all five algorithms.
Code –
import time
import random
import math
import pandas as pd
import matplotlib.pyplot as plt
# 1. Algorithm implementations for different time complexities
def constant_time(arr):
# O(1) — just return first element or a constant operation
if arr:
return arr[0]
return None
def linear_time(arr):
# O(n) — sum all elements
total = 0
for num in arr:
total += num
return total
def quadratic_time(arr):
# O(n^2) — nested loops, count pairs that sum to zero (example)
count = 0
n = len(arr)
for i in range(n):
for j in range(n):
if i != j and arr[i] + arr[j] == 0:
count += 1
return count
def logarithmic_time(arr):
# O(log n) — binary search for a number (we pick middle element)
arr_sorted = sorted(arr)
target = arr_sorted[len(arr_sorted)//2] if arr_sorted else None
def binary_search(array, target):
low, high = 0, len(array) - 1
while low <= high:
mid = (low + high) // 2
if array[mid] == target:
return mid
elif array[mid] < target:
low = mid + 1
else:
high = mid - 1
return -1
return binary_search(arr_sorted, target)
def linearithmic_time(arr):
# O(n log n) — sorting the array
return sorted(arr)
# 2 & 3. Measure execution time for different input sizes
input_sizes = [10, 100, 500, 1000, 2000, 5000, 10000]
times_O1 = []
times_On = []
times_On2 = []
times_Ologn = []
times_Onlogn = []
for size in input_sizes:
arr = [random.randint(-1000, 1000) for _ in range(size)]
start = time.time()
constant_time(arr)
end = time.time()
times_O1.append(end - start)
start = time.time()
linear_time(arr)
end = time.time()
times_On.append(end - start)
if size <= 1000:
start = time.time()
quadratic_time(arr)
end = time.time()
times_On2.append(end - start)
else:
times_On2.append(None)
start = time.time()
logarithmic_time(arr)
end = time.time()
times_Ologn.append(end - start)
start = time.time()
linearithmic_time(arr)
end = time.time()
times_Onlogn.append(end - start)
# 4. Save results to CSV
data = {
'Input Size': input_sizes,
'O(1)': times_O1,
'O(n)': times_On,
'O(n^2)': times_On2,
'O(log n)': times_Ologn,
'O(n log n)': times_Onlogn
df = pd.DataFrame(data)
df.to_csv('execution_times.csv', index=False)
print("Execution times saved to 'execution_times.csv'")
# 4. Plotting results
plt.figure(figsize=(14, 7))
plt.plot(input_sizes, times_O1, marker='o', linewidth=2, label='O(1)')
plt.plot(input_sizes, times_On, marker='o', linewidth=2, label='O(n)')
plt.plot(input_sizes[:4], times_On2[:4], marker='o', linewidth=2,
label='O(n^2)')
plt.plot(input_sizes, times_Ologn, marker='o', linewidth=2, label='O(log n)')
plt.plot(input_sizes, times_Onlogn, marker='o', linewidth=2, label='O(n log
n)')
plt.title('Execution Time vs Input Size')
plt.xlabel('Input Size')
plt.ylabel('Execution Time (seconds)')
plt.grid(True, linestyle='--', alpha=0.6)
plt.legend()
plt.tight_layout()
plt.show()