Module_1 - Intro_to_algorithm_analysis
Module_1 - Intro_to_algorithm_analysis
Table of Contents
What is an Algorithm?
Measure efficiency: Understand how fast an algorithm runs and how much
memory it uses.
Compare algorithms: Decide which algorithm is better suited for a problem.
Optimize performance: Improve existing algorithms or design new ones.
Predict scalability: Assess how an algorithm behaves as the input size
grows.
Types of Analysis
Algorithms are analyzed for both time complexity and space complexity:
Asymptotic Notations
Asymptotic notations are used to express the growth of an algorithm's time or space
requirements:
For instance, consider a function that calculates the sum of the first n integers:
Characteristics of algorithm
1. Input
Definition: An algorithm must have well-defined inputs. These are the values
or data that are provided to the algorithm before it starts its execution.
Requirements:
o The number and type of inputs should be specified.
o Inputs can be zero, one, or more depending on the problem.
Example:
o A sorting algorithm requires an array or list of numbers as input.
o A factorial algorithm may take a single integer as input.
2. Output
Definition: An algorithm must produce at least one output, which is the result
of processing the input through its steps.
Requirements:
o The output should be well-defined and related to the input.
o The output must meet the problem's requirements.
Example:
o A sorting algorithm outputs the same numbers in a sorted order.
Definition: Every step of the algorithm must be clearly and precisely defined,
with no ambiguity in what action is to be performed.
Requirements:
o Each step must have only one interpretation.
o The instructions must be executable and understandable.
Importance: Ambiguous instructions can lead to errors or incorrect outputs.
Example:
o "Add 2 to the current value" is definite.
o "Do something to get a result" is ambiguous and not acceptable.
4. Finiteness
5. Effectiveness
6. Correctness
7. Generality
9. Independence
Pseudocode:
1. Input n.
2. Initialize result = 1.
3. For i = 1 to n:
o Multiply result by i.
4. Output result.
Analysis:
Input: n, an integer.
Output: Factorial of n.
Definiteness: Each step is precise (e.g., initialize, multiply).
Finiteness: The loop runs n times and stops.
Effectiveness: The operations (multiplication, initialization) are simple.
Correctness: The algorithm correctly computes the factorial.
Generality: It works for any non-negative integer n.
2. Growth Rate:
o Describes how the resource consumption (time or space) of an
algorithm increases as n grows.
3. Asymptotic Notations:
o These are mathematical tools to describe the upper, lower, and tight
bounds of an algorithm's complexity.
Asymptotic Notations
Asymptotic notations describe how an algorithm's resource usage grows with input
size, abstracting away constants and lower-order terms.
f(n)∈O(g(n)) if there exist constants c>0 and n0 such that f(n) ≤c⋅g(n), ∀n≥n0.
Interpretation:
1. Time Complexity
Time complexity measures the amount of time an algorithm takes to complete its
task as a function of the input size (n). It evaluates the efficiency of the algorithm with
respect to execution time.
Mathematical Analysis:
2. Space Complexity
1. Input Space:
Iterative algorithms often have a lower space complexity than recursive ones
because they don’t require a call stack.
o Iterative factorial calculation: O(1) auxiliary space.
o Recursive factorial calculation: O(n) auxiliary space (for the recursion
stack).
Performance Metrics
1. Execution Time
2. Memory Usage
3. Input Size
The size of the input significantly affects both time and space complexity.
Algorithms often perform differently on small vs. large inputs.
Problem: Compare bubble sort and merge sort for sorting an array.
1. Bubble Sort:
o Time Complexity:
Worst-case: O(n2).
Best-case: O(n) (if already sorted).
o Space Complexity: O(1).
2. Merge Sort:
o Time Complexity:
Worst-case: O(nlogn).
Best-case: O(nlogn).
o Space Complexity: O(n) (due to auxiliary arrays).
Observation:
For large inputs, merge sort performs significantly better due to its lower time
complexity.
Bubble sort is simpler but impractical for large datasets.
1. Time-Optimized Algorithms:
o Focus on reducing execution time.
o Often require additional memory to store intermediate results or
precomputed data.
o Example: Using a hash table for fast lookups increases space usage
but reduces the time complexity from O(n) (linear search) to O(1)
(constant time).
2. Space-Optimized Algorithms:
o Focus on minimizing memory usage.
o Often require additional computations, increasing execution time.
o Example: Calculating Fibonacci numbers iteratively requires O(1)
space, but recursive methods with memoization require more memory
but reduce redundant calculations.
Dynamic Programming:
o Uses additional memory to store results of subproblems (memoization).
o Reduces time complexity by avoiding redundant calculations.
o Example: Fibonacci sequence with memoization has O(n) time
complexity but O(n) space complexity.
Recursion:
o Minimizes space by not storing subproblem results.
o Increases time complexity due to redundant calculations.
o Example: Plain recursive Fibonacci sequence has O(2n) time
complexity and O(n) space complexity (for the recursion stack).
Merge Sort:
o Time Complexity: O(nlogn).
o Space Complexity: O(n) (requires auxiliary arrays).
In-Place Sorting (e.g., Quick Sort):
o Time Complexity: O(nlogn) on average.
o Space Complexity: O(logn) (due to recursion stack).
Hashing:
o Uses extra memory for hash tables.
o Achieves constant-time lookups O(1).
Brute Force:
o Requires no additional memory.
o Takes O(n) time for lookups in unsorted data.
4. Data Compression
Compressed data uses less space but requires more time to decompress
when accessed.
Example: Compressed image files save storage but increase the time
required for decompression during viewing.
Substitution method
1. Hypothesize a Solution:
2. Prove by Induction:
o Use mathematical induction to prove that the hypothesis is valid.
o Show that the solution holds for a base case (small values of nnn).
o Assume that the solution holds for some k (T(k)).
o Prove that it holds for k+1 (T(k+1)).
3. Validate Constants:
o Adjust constants or coefficients in the hypothesis, if necessary, to make
the proof valid.
2. Complex Recurrences:
o For highly complex recurrence relations, guessing the solution can be
difficult.
3. Manual Adjustments:
o May require manual fine-tuning of constants to validate the proof.
The goal is to compute the total work done at all levels of the recursion and derive
the algorithm's overall complexity.
1. Write the Recurrence Relation: Start with the recurrence relation that
represents the algorithm's time complexity.
2. Expand the Recurrence: Break down the recurrence relation level by level
into its subproblems until reaching the base case.
3. Calculate Work per Level: Sum the work done at each level of the tree
(combine all nodes at the same depth).
4. Determine the Tree's Depth: Find the number of levels in the recursion tree,
which corresponds to the height of the tree.
5. Sum the Work Across All Levels: Add up the work done at all levels to
compute the total time complexity.
6. Identify Dominant Term: Use asymptotic analysis to determine the dominant
term in the final expression, which represents the overall time complexity.
1. Intuitive:
o Provides a clear, visual representation of recursive calls and their
associated costs.
3. Easier to Interpret:
o The level-wise breakdown helps in understanding the contributions of
different parts of the recursion.
Master’s theorem
Master’s Theorem is a powerful tool for analyzing the time complexity of divide-
and-conquer algorithms, particularly those that can be expressed using a specific
form of recurrence relation. It provides a straightforward way to derive asymptotic
bounds for such recurrences without requiring detailed expansions or
mathematical induction.
If any of these conditions are not met, Master’s Theorem does not apply.
1. Restricted Form:
o Only applies to recurrences of the specific form T(n)=aT(n/b)+f(n).
2. Non-Polynomial Functions:
o Does not handle f(n) with logarithmic or exponential growth effectively.
3. Regularity Conditions:
o Case 3 requires additional conditions for f(n) to dominate.
Summary
The study of algorithms is called algorithmics.
Algorithmics is more than a branch of computer science. It is the core of
computer science, and, in all fairness, can be said to be relevant to most of
science, business, and technology.
An Algorithm is a step-by-step process of solving a problem in a finite number
of steps.
Algorithms must have a unique name
Algorithms should have explicitly defined a set of inputs and outputs
Algorithms are well-ordered with unambiguous operations
Algorithms halt in a finite amount of time. Algorithms should not run for infinity,
i.e., an algorithm must end at some point
An algorithm design technique (or “strategy” or “paradigm”) is a general
approach to solving problems algorithmically that is applicable to a variety of
problems from different areas of computing.
There are two kinds of efficiency: Time efficiency and space efficiency.