This complete tutorial on Algorithms Using C++ explains time and space complexity analysis, sorting and searching algorithms, recursion, backtracking, greedy algorithms, and dynamic programming. Following best practices, it helps learners write efficient and optimized C++ programs for problem-solving and competitive programming.
Algorithms Using C++ – Complete Tutorial
1. Time and Space Complexity
Time Complexity
- Measures how fast an algorithm runs as input size grows
- Big O Notation examples:
- O(1) – Constant
- O(n) – Linear
- O(n²) – Quadratic
- O(log n) – Logarithmic
Space Complexity
- Measures extra memory used by an algorithm
- Includes recursion stack, auxiliary arrays, or hash tables
Example:
// Linear search O(n) time, O(1) space
int linearSearch(int arr[], int n, int key) {
for(int i=0; i<n; i++) if(arr[i]==key) return i;
return -1;
}
2. Sorting Algorithms
a) Bubble Sort – O(n²)
void bubbleSort(int arr[], int n) {
for(int i=0;i<n-1;i++)
for(int j=0;j<n-i-1;j++)
if(arr[j]>arr[j+1]) swap(arr[j],arr[j+1]);
}
b) Selection Sort – O(n²)
- Find min element and place at start
c) Insertion Sort – O(n²)
- Insert each element into sorted subarray
d) Merge Sort – O(n log n)
- Divide and conquer
#include <vector>
void mergeSort(vector<int>& arr, int l, int r);
e) Quick Sort – O(n log n) average
- Partition array around pivot
3. Searching Algorithms
a) Linear Search – O(n)
- Check each element sequentially
b) Binary Search – O(log n)
- Requires sorted array
int binarySearch(int arr[], int l, int r, int key) {
while(l<=r) {
int m = l + (r-l)/2;
if(arr[m]==key) return m;
if(arr[m]<key) l = m+1;
else r = m-1;
}
return -1;
}
4. Recursion
Recursion is when a function calls itself to solve a smaller problem.
Example: Factorial
int factorial(int n) {
if(n<=1) return 1;
return n * factorial(n-1);
}
Best Practices:
- Define base case
- Avoid deep recursion to prevent stack overflow
5. Backtracking
Backtracking is a trial-and-error approach to solve problems like N-Queens, Sudoku, maze solving.
Example: N-Queens
bool solve(int row, vector<int>& board);
Use Cases:
- Puzzle solving
- Constraint satisfaction problems
6. Greedy Algorithms
Greedy algorithms make locally optimal choices at each step to find global optimum.
Example: Coin Change (Greedy)
vector<int> coins = {25,10,5,1};
int amount = 63;
Use Cases:
- Minimum spanning tree (Prim, Kruskal)
- Huffman encoding
7. Dynamic Programming (DP)
DP solves problems by storing intermediate results (memoization/tabulation) to avoid recomputation.
Example: Fibonacci using DP
int fib(int n) {
vector<int> dp(n+1,0);
dp[1] = 1;
for(int i=2;i<=n;i++) dp[i] = dp[i-1]+dp[i-2];
return dp[n];
}
Best Practices:
- Identify overlapping subproblems
- Decide between top-down (memoization) or bottom-up (tabulation)
Best Practices
- Analyze time and space complexity before implementation
- Prefer efficient algorithms for large input
- Use STL functions (
sort,lower_bound,upper_bound) for fast implementation - Modularize code for recursive, greedy, or DP solutions
- Test algorithms on edge cases
Common Mistakes
- Ignoring base case in recursion
- Using greedy where DP is required
- Forgetting to sort for binary search
- Not considering time/space constraints for large inputs
Summary
In this chapter, you learned about Algorithms Using C++, including:
- Time and space complexity analysis
- Sorting and searching algorithms
- Recursion, backtracking
- Greedy algorithms
- Dynamic programming
Mastering algorithms is essential for efficient problem-solving, competitive programming, and real-world software development.