Definition: For loops are used to repeat operations for a specified number of iterations or for each element in a collection.
Syntax: The general syntax is:
for some_variable in range_of_values:
loop_body
Range Construction: For loops often utilize a range of integers, indicated by range(lowest, highest + 1)
. For example:
for i in range(0, 100): print(i)
outputs integers from 0 to 99.
Starting at zero can be simplified: for i in range(100): print(i)
.
Example: Calculating the factorial of a positive integer n
:
factorial = 1
for i in range(1, n + 1):
factorial *= i
Definition: While loops are employed when the number of iterations is not known beforehand. The loop continues until a specified condition evaluates to false.
Syntax: The syntax is:
while some_condition:
loop_body
Example: Counting the number of digits in a positive integer n
using arithmetic operations:
result = 0
while n > 0:
n //= 10
result += 1
Another Example: Printing Fibonacci numbers up to n
:
a, b = 0, 1
while a <= n:
print(a)
a, b = b, a + b
Definition: Using for loops to iterate over values in various collection types, including lists, sets, and dictionaries.
Example: Looping through a list of days:
days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
for day in days:
print(day)
Use of xrange
: When dealing with large ranges, consider xrange
, which generates values on the fly instead of storing them.
Basic for
loop with a set (order not guaranteed):
days_set = set(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'])
for day in days_set:
print(day)
Dictionaries: Looping through a dictionary holds keys, producing key-value pair outputs with arbitrary order:
days_dict = {'mon': 'Monday', 'tue': 'Tuesday'}
for key in days_dict:
print(key, 'stands for', days_dict[key])
Definition: Arrays are data structures to store multiple items in a single entity. Example for creating a shopping list:
shopping = ['bread', 'butter', 'cheese']
Accessing Values: Array elements can be accessed using their index:
shopping[0] # returns 'bread'
Arrays also can be empty:
shopping = []
Changing Values: Array elements can be modified directly by referencing their index:
shopping[1] = 'margarine'
Appending Values: Use +=
to add new items:
shopping += ['eggs']
Looping through arrays is common for counting or processing all elements. The array's length can be determined via len()
function:
N = len(shopping)
for i in range(N):
print(shopping[i])
Alternatively, iterating directly through the elements:
for item in shopping:
print(item)
Definition: Time complexity helps estimate the time an algorithm takes to run as the input size grows.
Common Operations: For example, a single addition or assignment doesn’t increase complexity significantly.
Constant Time – O(1) remains the same regardless of input size.
Logarithmic Time – O(log n), for example: halving each iteration reduces the number of required operations robustly.
Linear Time – O(n), where the runtime scales directly with output.
Quadratic Time – O(n^2), often seen in algorithms with nested iterations.
Exponential Time – O(2^n) or factorial time O(n!) are impractical for large numbers and require efficient alternatives.
Prime Numbers: Natural numbers greater than 1 that have exactly two divisors (1 and itself).
Composite Numbers: Numbers with more than two divisors.
Primality Testing: Use methods such as checking divisibility up to √n to efficiently determine if a number is prime.
Counting Divisors: Iterating through from 1 to n to determine how many number divides n
can be improved by checking up to √n.
def divisors(n):
count = 0
for i in range(1, int(n**0.5) + 1):
if n % i == 0:
count += 1
if i != n // i:
count += 1
return count
Definition: Fibonacci numbers where the first two numbers are 0 and 1 and each subsequent number is the sum of the previous two.
The recursive Fibonacci method is inefficient due to repeated calculations:
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
Dynamic Programming Approach: Improves efficiency by storing previously computed values:
def fibonacciDynamic(n):
fib = [0] * (n + 2)
fib[1] = 1
for i in range(2, n + 1):
fib[i] = fib[i - 1] + fib[i - 2]
return fib[n]
Matrix Multiplication Method: Calculates Fibonacci in O(log n) time utilizing matrix exponentiation for more efficiency:
def fibonacciMatrix(n):
def multiply(F, M):
x = F[0]*M[0] + F[1]*M[2]
y = F[0]*M[1] + F[1]*M[3]
F[0], F[1] = x, y