Understanding Time Complexity with Simple Examples
Last Updated :
16 Sep, 2024
A lot of students get confused while understanding the concept of time complexity, but in this article, we will explain it with a very simple example.
Q. Imagine a classroom of 100 students in which you gave your pen to one person. You have to find that pen without knowing to whom you gave it.
Here are some ways to find the pen and what the O order is.
- O(n2): You go and ask the first person in the class if he has the pen. Also, you ask this person about the other 99 people in the classroom if they have that pen and so on,
This is what we call O(n2). - O(n): Going and asking each student individually is O(N).
- O(log n): Now I divide the class into two groups, then ask: "Is it on the left side, or the right side of the classroom?" Then I take that group and divide it into two and ask again, and so on. Repeat the process till you are left with one student who has your pen. This is what you mean by O(log n).
I might need to do:
- The O(n2) searches if only one student knows on which student the pen is hidden.
- The O(n) if one student had the pen and only they knew it.
- The O(log n) search if all the students knew, but would only tell me if I guessed the right side.
The above O -> is called Big - O which is an asymptotic notation. There are other asymptotic notations like theta and Omega.
NOTE: We are interested in the rate of growth over time with respect to the inputs taken during the program execution.
Is the Time Complexity of an Algorithm/Code the same as the Running/Execution Time of Code?
The Time Complexity of an algorithm/code is not equal to the actual time required to execute a particular code, but the number of times a statement executes. We can prove this by using the time command.
For example: Write code in C/C++ or any other language to find the maximum between N numbers, where N varies from 10, 100, 1000, and 10000. For Linux based operating system (Fedora or Ubuntu), use the below commands:
To compile the program: gcc program.c – o program
To execute the program: time ./program
You will get surprising results i.e.:
- For N = 10: you may get 0.5 ms time,
- For N = 10,000: you may get 0.2 ms time.
- Also, you will get different timings on different machines. Even if you will not get the same timings on the same machine for the same code, the reason behind that is the current network load.
So, we can say that the actual time required to execute code is machine-dependent (whether you are using Pentium 1 or Pentium 5) and also it considers network load if your machine is in LAN/WAN.
What is meant by the Time Complexity of an Algorithm?
Now, the question arises if time complexity is not the actual time required to execute the code, then what is it?
The answer is:
Instead of measuring actual time required in executing each statement in the code, Time Complexity considers how many times each statement executes.
Example 1: Consider the below simple code to print Hello World
C++
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World";
return 0;
}
// This code is contributed by vikash36905.
C
#include <stdio.h>
int main()
{
printf("Hello World");
return 0;
}
Java
import java.io.*;
class GFG {
public static void main(String[] args)
{
System.out.print("Hello World");
}
}
// This code is contributed by vikash36905.
Python
print("Hello World")
# This code is contributed by akashish__
C#
using System;
public class GFG{
static public void Main (){
// Code
Console.WriteLine("Hello World");
}
}
// This code is contributed by lokesh
JavaScript
console.log("Hello World")
// This code is contributed by nilha72xi.
Time Complexity: In the above code “Hello World” is printed only once on the screen.
So, the time complexity is constant: O(1) i.e. every time a constant amount of time is required to execute code, no matter which operating system or which machine configurations you are using.
Auxiliary Space: O(1)
Example 2:
C++
#include <iostream>
using namespace std;
int main()
{
int i, n = 8;
for (i = 1; i <= n; i++) {
cout << "Hello World !!!\n";
}
return 0;
}
// This code is contributed by vikash36905.
C
#include <stdio.h>
void main()
{
int i, n = 8;
for (i = 1; i <= n; i++) {
printf("Hello World !!!\n");
}
}
Java
class GFG {
public static void main(String[] args)
{
int i, n = 8;
for (i = 1; i <= n; i++) {
System.out.printf("Hello World !!!\n");
}
}
}
// This code is contributed by Rajput-Ji
Python
# Python code
n = 8
for i in range(1, n + 1):
print("Hello World !!!")
# This code is contributed by lokesh
C#
using System;
public class GFG {
public static void Main(String[] args)
{
int i, n = 8;
for (i = 1; i <= n; i++) {
Console.Write("Hello World !!!\n");
}
}
}
// This code contributed by Rajput-Ji
JavaScript
let i, n = 8;
for (i = 1; i <= n; i++) {
console.log("Hello World !!!");
}
OutputHello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Time Complexity: In the above code “Hello World !!!” is printed only n times on the screen, as the value of n can change.
So, the time complexity is linear: O(n) i.e. every time, a linear amount of time is required to execute code.
Auxiliary Space: O(1)
Example 3:
C++
#include <iostream>
using namespace std;
int main()
{
int i, n = 8;
for (i = 1; i <= n; i=i*2) {
cout << "Hello World !!!\n";
}
return 0;
}
// This code is contributed by Suruchi Kumari
C
#include <stdio.h>
void main()
{
int i, n = 8;
for (i = 1; i <= n; i=i*2) {
printf("Hello World !!!\n");
}
}
// This code is contributed by Suruchi Kumari
Java
class GFG {
public static void main(String[] args)
{
int i, n = 8;
for (i = 1; i <= n; i=i*2) {
System.out.println("Hello World !!!");
}
}
}
// This code is contributed by Suruchi Kumari
Python
n = 8
# for (i = 1; i <= n; i=i*2) {
for i in range(1, n+1, 2):
print("Hello World !!!")
# This code is contributed by akashish__
C#
using System;
public class GFG{
static public void Main (){
// Code
int i, n = 8;
for (i = 1; i <= n; i=i*2) {
Console.Write("Hello World !!!\n");
}
}
}
// This code is contributed by lokeshmvs21.
JavaScript
for (i = 1; i <= 8; i=i*2) {
console.log("Hello World !!!");
}
// This code is contributed by nilha7xi.
OutputHello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Time Complexity: O(log2(n))
Auxiliary Space: O(1)
Example 4:
C++
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int i, n = 8;
for (i = 2; i <= n; i=pow(i,2)) {
cout << "Hello World !!!\n";
}
return 0;
}
// This code is contributed by Suruchi Kumari
C
#include <stdio.h>
#include <math.h>
void main()
{
int i, n = 8;
for (i = 2; i <= n; i=pow(i,2)) {
printf("Hello World !!!\n");
}
}
// This code is contributed by Suruchi Kumari
Java
import java.lang.Math;
class GFG {
public static void main(String args[]){
int i, n = 8;
for (i = 2; i <= n; i=(int)Math.pow(i,2)) {
System.out.println("Hello World !!!");
}
}
}
Python
n = 8
i = 2
for j in range(2,n+1):
if(i >= n):
break
print("Hello World !!!")
i *= i
# This code is contributed by akashish__
C#
using System;
using System.Collections.Generic;
public class GFG {
static public void Main()
{
int i, n = 8;
for (i = 2; i <= n; i = (int)Math.Pow(i, 2)) {
Console.WriteLine("Hello World !!!");
}
}
}
// This code is contributed by akashish__
JavaScript
for (let i = 2; i <= 8; i=Math.pow(i,2)) {
console.log("Hello World !!!");
}
// This code is contributed by nilha7xi.
OutputHello World !!!
Hello World !!!
Time Complexity: O(log(log n))
Auxiliary Space: O(1)
How To Find The Time Complexity Of An Algorithm?
Now let us see some other examples and the process to find the time complexity of an algorithm:
Example: Let us consider a model machine that has the following specifications:
- Single processor
- 32 bit
- Sequential execution
- 1 unit time for arithmetic and logical operations
- 1 unit time for assignment and return statements
Q1. Find the Sum of 2 numbers on the above machine:
For any machine, the pseudocode to add two numbers will be something like this:
C++
// Pseudocode : Sum(a, b) { return a + b }
#include <iostream>
using namespace std;
int sum(int a,int b)
{
return a+b;
}
int main() {
int a = 5, b = 6;
cout<<sum(a,b)<<endl;
return 0;
}
// This code is contributed by akashish__
C
Pseudocode : Sum(a, b) { return a + b }
Java
// Pseudocode : Sum(a, b) { return a + b }
import java.io.*;
class GFG {
public static int sum(int a, int b) { return a + b; }
public static void main(String[] args)
{
int a = 5, b = 6;
System.out.println(sum(a, b));
}
}
// This code is contributed by akashish__
Python
# Pseudocode : Sum(a, b) { return a + b }
a = 5
b = 6
def sum(a,b):
return a+b
# function call
print(sum(a,b))
C#
// Pseudocode : Sum(a, b) { return a + b }
using System;
public class GFG {
public static int sum(int a, int b) { return a + b; }
static public void Main()
{
int a = 5, b = 6;
Console.WriteLine(sum(a, b));
}
}
// This code is contributed by akashish__
JavaScript
// Pseudocode : Sum(a, b) { return a + b }
function sum(a, b) {
return a + b;
}
let a = 5, b = 6;
console.log(sum(a, b));
// This code is contributed by akashish__
Time Complexity:
- The above code will take 2 units of time(constant):
- one for arithmetic operations and
- one for return. (as per the above conventions).
- Therefore total cost to perform sum operation (Tsum) = 1 + 1 = 2
- Time Complexity = O(2) = O(1), since 2 is constant
Auxiliary Space: O(1)
Q2. Find the sum of all elements of a list/array
The pseudocode to do so can be given as:
C++
#include <iostream>
using namespace std;
int list_Sum(int A[], int n)
// A->array and
// n->number of elements in array
{
int sum = 0;
for (int i = 0; i <= n - 1; i++) {
sum = sum + A[i];
}
return sum;
}
int main()
{
int A[] = { 5, 6, 1, 2 };
int n = sizeof(A) / sizeof(A[0]);
cout << list_Sum(A, n);
return 0;
}
// This code is contributed by akashish__
C
Pseudocode : list_Sum(A, n)
// A->array and
// n->number of elements in array
{
sum = 0
for i = 0 to n-1
sum = sum + A[i]
return sum
}
Java
// Java code for the above approach
import java.io.*;
class GFG {
static int list_Sum(int[] A, int n)
// A->array and
// n->number of elements in array
{
int sum = 0;
for (int i = 0; i <= n - 1; i++) {
sum = sum + A[i];
}
return sum;
}
public static void main(String[] args)
{
int[] A = { 5, 6, 1, 2 };
int n = A.length;
System.out.println(list_Sum(A, n));
}
}
// This code is contributed by lokeshmvs21.
Python
# A function to calculate the sum of the elements in an array
def list_sum(A, n):
sum = 0
for i in range(n):
sum += A[i]
return sum
# A sample array
A = [5, 6, 1, 2]
# Finding the number of elements in the array
n = len(A)
# Call the function and print the result
print(list_sum(A, n))
C#
using System;
public class GFG {
public static int list_Sum(int[] A, int n)
// A->array and
// n->number of elements in array
{
int sum = 0;
for (int i = 0; i <= n - 1; i++) {
sum = sum + A[i];
}
return sum;
}
static public void Main()
{
int[] A = { 5, 6, 1, 2 };
int n = A.Length;
Console.WriteLine(list_Sum(A, n));
}
}
// This code is contributed by akashish__
JavaScript
function list_Sum(A, n)
// A->array and
// n->number of elements in array
{
let sum = 0;
for (let i = 0; i <= n - 1; i++) {
sum = sum + A[i];
}
return sum;
}
let A = [ 5, 6, 1, 2 ];
let n = A.length;
console.log(list_Sum(A, n));
// This code is contributed by akashish__
To understand the time complexity of the above code, let's see how much time each statement will take:
C++
int list_Sum(int A[], int n)
{
int sum = 0; // cost=1 no of times=1
for(int i=0; i<n; i++) // cost=2 no of times=n+1 (+1 for the end false condition)
sum = sum + A[i] ; // cost=2 no of times=n
return sum ; // cost=1 no of times=1
}
C
Pseudocode : list_Sum(A, n)
{
total =0 // cost=1 no of times=1
for i=0 to n-1 // cost=2 no of times=n+1 (+1 for the end false condition)
sum = sum + A[i] // cost=2 no of times=n
return sum // cost=1 no of times=1
}
Java
public class ListSum {
// Function to calculate the sum of elements in an array
static int listSum(int[] A, int n) {
int sum = 0; // Cost = 1, executed 1 time
for (int i = 0; i < n; i++) { // Cost = 2, executed n+1 times (+1 for
// the end false condition)
sum = sum + A[i]; // Cost = 2, executed n times
}
return sum; // Cost = 1, executed 1 time
}
// Main method for testing
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5};
int length = array.length;
int result = listSum(array, length);
System.out.println("Sum: " + result);
}
}
Python
def list_sum(A):
sum = 0
for i in range(len(A)):
sum = sum + A[i]
return sum
C#
using System;
class Program
{
// Function to calculate the sum of elements in a list
static int ListSum(int[] A)
{
int sum = 0; // Initialize sum to 0
// Loop to iterate through the array elements
for (int i = 0; i < A.Length; i++)
{
sum = sum + A[i]; // Accumulate the sum
}
return sum; // Return the calculated sum
}
// Driver code
static void Main()
{
// Example usage
int[] array = { 1, 2, 3, 4, 5 };
int result = ListSum(array);
Console.WriteLine(result);
}
}
JavaScript
function listSum(A) {
let sum = 0; // Initialize sum to 0
// Loop to iterate through the array elements
for (let i = 0; i < A.length; i++) {
sum = sum + A[i]; // Accumulate the sum
}
return sum; // Return the calculated sum
}
// Example usage
let array = [1, 2, 3, 4, 5];
let result = listSum(array);
console.log(result);
Therefore the total cost to perform sum operation
Tsum=1 + 2 * (n+1) + 2 * n + 1 = 4n + 4 =C1 * n + C2 = O(n)
Therefore, the time complexity of the above code is O(n)
Q3. Find the sum of all elements of a matrix
For this one, the complexity is a polynomial equation (quadratic equation for a square matrix)
- Matrix of size n*n => Tsum = a.n2 + b.n + c
- Since Tsum is in order of n2, therefore Time Complexity = O(n2)
C++
#include <iostream>
using namespace std;
int main()
{
int n = 3;
int m = 3;
int arr[][3]
= { { 3, 2, 7 }, { 2, 6, 8 }, { 5, 1, 9 } };
int sum = 0;
// Iterating over all 1-D arrays in 2-D array
for (int i = 0; i < n; i++) {
// Printing all elements in ith 1-D array
for (int j = 0; j < m; j++) {
// Printing jth element of ith row
sum += arr[i][j];
}
}
cout << sum << endl;
return 0;
}
// contributed by akashish__
Java
/*package whatever //do not write package name here */
import java.io.*;
class GFG {
public static void main(String[] args)
{
int n = 3;
int m = 3;
int arr[][]
= { { 3, 2, 7 }, { 2, 6, 8 }, { 5, 1, 9 } };
int sum = 0;
// Iterating over all 1-D arrays in 2-D array
for (int i = 0; i < n; i++) {
// Printing all elements in ith 1-D array
for (int j = 0; j < m; j++) {
// Printing jth element of ith row
sum += arr[i][j];
}
}
System.out.println(sum);
}
}
// akashish__
Python
n = 3
m = 3
arr = [[3, 2, 7], [2, 6, 8], [5, 1, 9]]
sum = 0
# Iterating over all 1-D arrays in 2-D array
for i in range(n):
# Printing all elements in ith 1-D array
for j in range(m):
# Printing jth element of ith row
sum += arr[i][j]
print(sum)
# This code id contributed by shivhack999
C#
using System;
class MainClass {
static void Main(string[] args)
{
int n = 3;
int m = 3;
int[, ] arr
= { { 3, 2, 7 }, { 2, 6, 8 }, { 5, 1, 9 } };
int sum = 0;
// Iterating over all 1-D arrays in 2-D array
for (int i = 0; i < n; i++) {
// Printing all elements in ith 1-D array
for (int j = 0; j < m; j++) {
// Printing jth element of ith row
sum += arr[i, j];
}
}
Console.WriteLine(sum);
}
}
JavaScript
let n = 3;
let m = 3;
let arr = [[3, 2, 7], [2, 6, 8], [5, 1, 9]];
let sum = 0;
// Iterating over all 1-D arrays in 2-D array
for (let i = 0; i < n; i++) {
// Printing all elements in ith 1-D array
for (let j = 0; j < m; j++) {
// Printing jth element of ith row
sum += arr[i][j];
}
}
console.log(sum);
Time Complexity: O(n*m)
The program iterates through all the elements in the 2D array using two nested loops. The outer loop iterates n times and the inner loop iterates m times for each iteration of the outer loop. Therefore, the time complexity of the program is O(n*m).
Auxiliary Space: O(n*m)
The program uses a fixed amount of auxiliary space to store the 2D array and a few integer variables. The space required for the 2D array is nm integers. The program also uses a single integer variable to store the sum of the elements. Therefore, the auxiliary space complexity of the program is O(nm + 1), which simplifies to O(n*m).
In conclusion, the time complexity of the program is O(nm), and the auxiliary space complexity is also O(nm).
So from the above examples, we can conclude that the time of execution increases with the type of operations we make using the inputs.
[embed]https://www.youtube.com/watch?v=KXAbAa1mieU%5B/embed%5D
How to Compare Algorithms?
To compare algorithms, let us define a few objective measures:
- Execution times: Not a good measure as execution times are specific to a particular computer.
- The number of statements executed: Not a good measure, since the number of statements varies with the programming language as well as the style of the individual programmer.
- Ideal solution: Let us assume that we express the running time of a given algorithm as a function of the input size n (i.e., f(n)) and compare these different functions corresponding to running times. This kind of comparison is independent of machine time, programming style, etc.
Therefore, an ideal solution can be used to compare algorithms.
Related articles:
Calculating Time Complexity
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem