Understanding Time Complexity - The Big (O) Notation
Introduction
In computer science, algorithms play an important role in solving problem and optimizing processes. A key factor in evaluating the efficiency of these algorithms is the concept of time complexity. In this article we will try and make sense of time complexity, notations and their real world implications.
Definitions:
Sorting algorithms in C with Big (O)
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
// Stack structure
typedef struct {
int items[MAX_SIZE];
int top;
} Stack;
// Function to initialize the stack
void initialize(Stack *stack) {
stack->top = -1;
}
// Function to check if the stack is empty
int isEmpty(Stack *stack) {
return stack->top == -1;
}
// Function to push an element onto the stack
void push(Stack *stack, int value) {
if (stack->top == MAX_SIZE - 1) {
printf("Stack overflow\n");
return;
}
stack->items[++stack->top] = value;
}
// Function to pop an element from the stack
int pop(Stack *stack) {
if (isEmpty(stack)) {
printf("Stack underflow\n");
exit(1); // Terminate the program in case of underflow
}
return stack->items[stack->top--];
}
int main() {
Stack myStack;
initialize(&myStack);
push(&myStack, 10);
push(&myStack, 20);
push(&myStack, 30);
printf("Popped: %d\n", pop(&myStack)); // Should print "Popped: 30"
printf("Popped: %d\n", pop(&myStack)); // Should print "Popped: 20"
return 0;
}
Explanation:
Regardless of the number of elements in the stack, the time it takes to pop an element is constant, making the time complexity O(1).
2. O(n) - Linear Time: An algorithm with O(n) time complexity takes time linearly proportional to the size of the input data. Let's analyze the time complexity of the provided function:
#include <stdio.h> // Include the necessary header file
void f(int n)
{
int i;
for (i = 0; i < n; i += 98)
{
printf("[%d]\n", i);
}
}
int main() // Add a main function
{
f(500); // Call the function with an example value
return 0; // Return 0 to indicate successful execution
}
Explanation:
In this function, the loop is incrementing the variable i by 98 in each iteration. The loop runs as long as i is less than n.
The number of iterations k can be expressed as:
k=n/98
The time complexity of this function is O(n/98), but when we express it using Big O notation, we drop the constant factor. Therefore, the time complexity is O(n).
In simpler terms, the time complexity of this function is linear (O(n)), meaning the number of iterations and the running time grow linearly with the input size n.
3. Logarithmic Time Complexity (O(log n)):Indicates an algorithm's efficiency in dividing the problem size by a constant factor in each step. Logarithmic time complexities often signify efficient algorithms, especially in search or divide-and-conquer scenarios.
Let's analyze the time complexity of the provided function:
#include <stdio.h> // Include the necessary header file
void f(unsigned int n)
{
int i;
for (i = 1; i < n; i = i * 2)
{
printf("[%d]\n", i);
}
}
int main() // Add a main function
{
f(100); // Call the function with an example value
return 0; // Return 0 to indicate successful execution
}
Explanation:
This function prints values in a loop where i is doubled in each iteration until it reaches or exceeds the value of n. Let's break it down:
Let's see the iterations for n = 100:
The loop stops here because the next value, i=128, exceeds the specified value n = 100.
Time Complexity Analysis:
The time complexity of this loop is O(log2n). The number of iterations is proportional to the logarithm (base 2) of the input value n.
N/B. The notation O(logn) in the context of binary search represents the logarithm with base 2. The base of the logarithm is typically not explicitly mentioned because, in algorithmic analysis, logarithmic complexities are often assumed to have a base of 2 unless otherwise specified.
Relationship between Iterations and Time Complexity:
4. O(nlogn) - "linearithmic" or "quasilinear: It combines elements of both linear and logarithmic growth. Here's a breakdown of the components:
#include <stdio.h>
void f(unsigned int n)
{
int i;
int j;
for (i = 0; i < n; i++)
{
for (j = 1; j < n; j = j * 2)
{
printf("[%d] [%d]\n", i, j);
}
}
}
int main() {
f(10);
return 0;
}
Explanation:
The function f has a nested loop structure with an outer loop iterating over i and an inner loop iterating over j. The inner loop doubles the value of j in each iteration until it is greater than or equal to n.
Now, let's predict the output for f(10):
The outer loop runs for i from 0 to 9 (10 iterations). For each i, the inner loop runs for j starting from 1 and doubling its value until it becomes greater than or equal to 10.
领英推荐
The output will consist of pairs of [i] [j]. Let's go through a few iterations:
This pattern repeats for each iteration of the outer loop.
So, the output will contain pairs of [i] [j], where i is the outer loop variable and j is the inner loop variable. However, the output will not include all possible combinations of i and j due to the condition in the inner loop. The values of j will be powers of 2 until they exceed or equal n.
Time Complexity Analysis:
The outer loop runs n times, and the inner loop runs until j becomes greater than or equal to n. The inner loop has a geometric progression with the base of 2 (j = j * 2), which means it effectively runs in logarithmic time.
The total number of iterations can be calculated by multiplying the number of iterations of the outer loop by the number of iterations of the inner loop.
Let's denote the number of iterations of the outer loop as O and the number of iterations of the inner loop as I.
O×I=n×log2(n)
So, the time complexity of the function is O(nlogn). The inner loop is the dominant factor in determining the overall time complexity.
5. O(n^2) - "quadratic time complexity": The number of operations grows quadratically with the number of elements in the array (n).Quadratic time complexity is often associated with algorithms that involve nested loops, where the number of iterations in the inner loop is directly related to the size of the input in the outer loop. Examples include certain inefficient sorting algorithms like bubble sort and insertion sort.
Bubble Sort Overview:
#include <stdio.h>
// Function to perform Bubble Sort
void bubbleSort(int arr[], int n) {
int i, j;
// Outer loop: Iterate over each element in the array
for (i = 0; i < n-1; i++) {
// Inner loop: Compare and swap adjacent elements to push the larger elements to the end
for (j = 0; j < n-i-1; j++) {
// Compare adjacent elements and swap them if they are in the wrong order
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
int main() {
// Array to be sorted
int arr[] = {64, 34, 25, 12, 22, 11, 90};
// Calculate the number of elements in the array
int n = sizeof(arr)/sizeof(arr[0]);
// Call the bubbleSort function to sort the array
bubbleSort(arr, n);
// Print the sorted array
printf("Sorted array: \n");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}
Explanation:
Therefore, the time complexity of Bubble Sort is O(n^2), indicating a quadratic growth in the number of operations as the size of the input array increases. The nested loops and the way elements are compared and swapped contribute to this quadratic time complexity.
Singly linked list Operations
The time complexity of inserting after the nth element of a singly linked list, when using a sorting algorithm, depends on how you find the nth element. Let's consider a few scenarios:
1. Accessing a Node:
2. Searching for a Node:
3. Deleting a Node:
4. Inserting After a Node:
Doubly-linked lists Operations
1. Accessing a Node:
2. Searching for a Node:
3. Deleting a Node:
4. Inserting After a Node:
Conclusion
Understanding time complexity is crucial for assessing the efficiency of algorithms. Whether an algorithm exhibits constant, linear, logarithmic, or linearithmic time complexity can significantly impact its performance in real-world applications. By comprehending these complexities and their implications, developers can make informed decisions when selecting or designing algorithms for various computational
Pursuing Bachelors of Information Technology at Sk Somaiya College.
8 个月It helped me a lot I'm really thankful
Molecular biologist| Data Analyst| Back end Developer
1 年?? Can you crack the code and figure out the time complexity of this function? ?? Leave your thoughts in the comments, and let's unravel the algorithmic mystery together! ??