When we solve a problem using a computer, we need more than just code. Before writing the code, we need to think about how the problem should be solved. There can be multiple ways to solve the same problem. Some approaches may be simple but inefficient, while others may require more thought but perform much better as the size of the problem increases.
This is where Design and Analysis of Algorithms (DAA) comes in. DAA is not simply about learning different algorithms. It is about understanding how algorithms are designed, how we determine whether they are correct, and how we analyze their efficiency.
What is an Algorithm?
An algorithm is a finite sequence of well-defined steps used to solve a problem or perform a computation.
For example, if we want to find the largest number among a collection of numbers, we can start with the first number as the largest, compare it with every other number, and update the largest value whenever we find a bigger one.
These steps form an algorithm.
The important point is that an algorithm describes the logic and procedure for solving a problem, independent of a particular programming language.
We can later implement the same algorithm using C, C++, Java, Python, or another programming language.
What is Design of Algorithms?
Algorithm design is the process of developing a suitable method to solve a computational problem.
When designing an algorithm, we don’t simply look for any solution. We try to find a solution that is: Correct, Efficient, Clear, Practical, Scalable.
Different problems may require different design strategies.
Some of the important algorithm design approaches that we will study in this series include:
- Brute Force
- Divide and Conquer
- Greedy Method
- Dynamic Programming
- Backtracking
- Branch and Bound
- Randomized Algorithms
The real skill is learning to recognize which approach is appropriate for a particular problem.
What is Analysis of Algorithms?
After designing an algorithm, an important question remains: How good is the algorithm?
This is the purpose of algorithm analysis. We analyze an algorithm to understand how many computational resources it requires as the size of the input increases.
The two major resources we study are:
Time Complexity
Time complexity describes how the computational work performed by an algorithm grows with the size of its input.
For example, an algorithm whose number of operations grows roughly in proportion to n has a different performance characteristic from one whose operations grow in proportion to n².
We commonly express this growth using asymptotic notation, such as: O(1), O(log n), O(n), O(n log n), O(n²), and so on.
The purpose is not necessarily to calculate the exact time in seconds. Instead, we want to understand the growth of the algorithm as the input becomes larger.
Space Complexity
Space complexity describes how the memory requirements of an algorithm grow with the input size. An algorithm may require additional memory to store temporary values, intermediate results, recursive calls, or other information.
Therefore, when comparing algorithms, we may need to consider both time and space.
Correctness of an Algorithm
Efficiency alone does not make an algorithm good. An algorithm must first produce the correct result. DAA therefore also deals with methods for reasoning about and proving algorithm correctness. One important technique is the loop invariant, which helps us prove that a certain property remains true throughout the execution of a loop.
Correctness proofs allow us to move beyond simply testing an algorithm on a few examples and instead reason about whether it works for all valid inputs.
Why Do We Need Algorithm Analysis?
Consider two algorithms that solve the same problem. Both may produce the correct answer. But suppose one performs approximately n operations while another performs approximately n² operations. For a small input, the difference may not seem significant. But as n becomes very large, the difference can become enormous. This is why algorithm analysis matters.
We don’t just want an algorithm that works. We want to understand how its performance changes when the problem becomes larger.
This idea of scalability is one of the most important reasons for studying DAA.
DAA Is About Problem-Solving
One of the most valuable things about DAA is that it teaches a way of thinking. Instead of immediately writing code, we learn to ask:
- What is the problem?
- What are the possible approaches?
- Can the problem be divided into smaller problems?
- Can we make a locally optimal choice?
- Can we reuse solutions to smaller problems?
- Can we prove that our approach is correct?
- How efficient is the solution?
These questions help us develop algorithms systematically rather than solving problems through trial and error.
What Will We Cover in This DAA Series?
This article marks the beginning of my Design and Analysis of Algorithms series.
The series will move from algorithm analysis and correctness to recurrence relations, major algorithm design techniques, and finally computational complexity.
1. Algorithm Analysis
- Best-Case, Average-Case and Worst-Case Analysis
- Growth of Functions in Algorithm Analysis
- Comparing Algorithm Complexities
- Time-Space Trade-Off in Algorithms
2. Algorithm Correctness
- Why Algorithm Correctness Matters
- Loop Invariants
- Mathematical Induction in Algorithm Analysis
- Proving an Algorithm Correct
3. Asymptotic Analysis
- Big-O, Big-Ω and Big-Θ
- Comparing Growth Rates
- Common Complexity Classes
- Analyzing Algorithm Efficiency
4. Recurrence Relations
- Understanding Recurrence Relations
- Formulating Recurrences
- Substitution Method
- Recursion Tree Method
- Master Theorem
5. Brute Force
- Brute Force Strategy
- When to Use Brute Force
- Advantages and Limitations
- Examples of Brute Force Algorithms
6. Divide and Conquer
- Divide and Conquer Strategy
- Breaking Problems into Subproblems
- Combining Solutions
- Recurrence Analysis
- Applications of Divide and Conquer
7. Greedy Method
- Greedy Strategy
- Greedy Choice Property
- Optimal Substructure
- When Greedy Algorithms Work
- Applications of the Greedy Method
8. Dynamic Programming
- Principle of Dynamic Programming
- Overlapping Subproblems
- Optimal Substructure
- Memoization
- Tabulation
- Designing Dynamic Programming Solutions
9. Backtracking
- Backtracking Strategy
- Exploring the Solution Space
- Backtracking vs Brute Force
- Pruning Invalid Solutions
- Applications of Backtracking
10. Branch and Bound
- Branch and Bound Strategy
- Bounding the Search Space
- Branch and Bound vs Backtracking
- Applications to Optimization Problems
11. Randomized Algorithms
- Introduction to Randomized Algorithms
- Why Use Randomness?
- Las Vegas Algorithms
- Monte Carlo Algorithms
- Applications of Randomized Algorithms
12. Computational Complexity
- Introduction to Computational Complexity
- Polynomial-Time Algorithms
- Exponential-Time Algorithms
- P and NP
- NP-Hard Problems
- NP-Complete Problems
- Polynomial-Time Reductions
- Why Some Problems Are Difficult to Solve
The Goal of This Series
The goal of this series is not to memorize a collection of algorithms. I want to understand how algorithms are designed, why they work, how their correctness can be established, and how their efficiency can be analyzed.
Because ultimately, algorithmic thinking is not just about knowing a solution. It is about knowing why that solution works and whether there is a better way to solve the problem.
This is the beginning of my DAA series.
Let’s start with the fundamentals and build from there.

