In [1]:
import random
from matplotlib import pyplot as plt
from matplotlib.ticker import ScalarFormatter
In [2]:
def recursive_find_smallest(A):
    if len(A) < 2:
        return A

    head = [A[0]] # A list with a single element
    tail = A[1:]
    
    smallest_in_tail = recursive_find_smallest(tail)

    if smallest_in_tail < head:
        return smallest_in_tail

    return head
In [3]:
def recursive_find_smallest_dc(A, low=0, high=None):
    # Initialize the high pointer on the very first call
    if high is None:
        high = len(A) - 1
        
    # Base case: If the section only has one element, it is the minimum
    if low == high:
        return A[low]
        
    # Divide: Find the midpoint of the current section
    mid = (low + high) // 2
    
    # Conquer: Recursively find the minimum of both halves
    min_left = recursive_find_smallest_dc(A, low, mid)
    min_right = recursive_find_smallest_dc(A, mid + 1, high)
    
    # Combine: Return the smaller of the two minimums
    if min_left < min_right:
        return min_left
    else:
        return min_right
In [4]:
list_sizes = [10, 100, 1000, 10000, 100000, 1000000, 10000000]
for n in list_sizes:
    A = random.sample(range(1, n * 5), n)
    %timeit recursive_find_smallest_dc(A)
864 ns ± 12.5 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
10.9 μs ± 1.28 μs per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
148 μs ± 2.17 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
The slowest run took 9.08 times longer than the fastest. This could mean that an intermediate result is being cached.
3.74 ms ± 3.5 ms per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
33.3 ms ± 18.6 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
The slowest run took 4.76 times longer than the fastest. This could mean that an intermediate result is being cached.
259 ms ± 179 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
The slowest run took 4.29 times longer than the fastest. This could mean that an intermediate result is being cached.
5.03 s ± 3.02 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [7]:
# runtimes = [0.000908, 0.0231, 1.19, 1.55, 21.6, 294, 4930]
runtimes = [0.000864, 0.0109, 0.148, 3.74, 33.3, 259, 5030]

plt.plot(list_sizes, runtimes, marker='o') # Added marker to see points

plt.xscale('log')
plt.yscale('log')

# Create the formatter
formatter = ScalarFormatter()
formatter.set_scientific(False)

# Apply to BOTH axes manually
ax = plt.gca()
ax.xaxis.set_major_formatter(formatter)
ax.yaxis.set_major_formatter(formatter)

plt.title("Runtime vs List Size")
plt.xlabel("List Size")
plt.ylabel("Runtime (ms)")

# plt.ticklabel_format(style='plain', axis='both')  <-- REMOVE THIS LINE

plt.grid(True, which="both", ls="-", alpha=0.5) # Optional: helps see log scale
plt.show()
No description has been provided for this image
In [6]:
def minimum_from_exercise_6(A):
    v = A[0]                 
    for j in range(1, len(A)):   
        if A[j] < v:
            v = A[j]
    return v

%timeit minimum_from_exercise_6(A)
1.89 s ± 17.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)