0% found this document useful (0 votes)
8 views26 pages

DSA Theory

The document provides an overview of time and space complexity, explaining their definitions, common types, and examples. It covers searching algorithms like linear and binary search, along with sorting algorithms such as bubble sort and selection sort, detailing their processes, time complexities, and space complexities. Key comparisons between linear and binary search, as well as bubble and selection sort, are also included.

Uploaded by

naitikkashyap000
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views26 pages

DSA Theory

The document provides an overview of time and space complexity, explaining their definitions, common types, and examples. It covers searching algorithms like linear and binary search, along with sorting algorithms such as bubble sort and selection sort, detailing their processes, time complexities, and space complexities. Key comparisons between linear and binary search, as well as bubble and selection sort, are also included.

Uploaded by

naitikkashyap000
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

1. What is Time Complexity?

Time complexity tells us how the execution time of a program increases when the input size
increases.

It does not measure time in seconds.​


It measures the number of operations performed by the algorithm.

We express time complexity using Big-O notation.

2. Common Time Complexities (with Examples)

2.1 O(1) – Constant Time

The program takes the same time, no matter how large the input is.

Example:

int getFirst(int arr[]) {


return arr[0];
}

Explanation:

●​ Only one operation is performed.


●​ Input size does not matter.

Time Complexity = O(1)

2.2 O(n) – Linear Time

The execution time increases linearly with input size.

Example:

void printArray(int arr[], int n) {


for(int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
}
Explanation:

●​ Loop runs n times.


●​ If n doubles, time doubles.

Time Complexity = O(n)

2.3 O(n²) – Quadratic Time

Time increases very fast because of nested loops.

Example:

void printPairs(int n) {
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
printf("* ");
}
}
}

Explanation:

●​ Outer loop runs n times.


●​ Inner loop runs n times for each outer loop.
●​ Total operations = n × n.

Time Complexity = O(n²)

2.4 O(log n) – Logarithmic Time

The problem size is reduced by half in each step.

Example:

int binarySearch(int arr[], int n, int key) {


int low = 0, high = n - 1;
while(low <= high) {
int mid = (low + high) / 2;
if(arr[mid] == key)
return mid;
else if(arr[mid] < key)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}

Explanation:

●​ Search space reduces by half each time.


●​ Very efficient for large inputs.

Time Complexity = O(log n)

3. What is Space Complexity?

Space complexity tells us how much extra memory an algorithm uses apart from the input.

It includes:

●​ Variables
●​ Arrays
●​ Recursion stack

4. Common Space Complexities (with Examples)

4.1 O(1) – Constant Space

Uses a fixed amount of memory.

Example:

int sum(int a, int b) {


int result = a + b;
return result;
}

Explanation:
●​ Only one variable is used.
●​ Memory does not grow with input.

Space Complexity = O(1)

4.2 O(n) – Linear Space

Memory increases with input size.

Example:

void storeElements(int n) {
int arr[n];
}

Explanation:

●​ Array size depends on n.

Space Complexity = O(n)

4.3 O(n) – Recursion Stack Space

Each recursive call takes memory on the stack.

Example:

int factorial(int n) {
if(n == 0)
return 1;
return n * factorial(n - 1);
}

Explanation:

●​ For n, there are n function calls.


●​ Each call occupies memory.

Space Complexity = O(n)


5. Time vs Space Complexity (Quick Comparison)

Aspect Time Complexity Space Complexity

Measures Execution time Memory usage

Depends on Number of operations Extra memory


used

Important for Speed Memory efficiency

6. Key Points

●​ Loops affect time complexity


●​ Arrays and recursion affect space complexity
●​ Ignore constants (O(2n) = O(n))
●​ Nested loops usually mean O(n²)

Searching in Arrays

Definition

Searching in arrays refers to the process of finding the position (index) of a given element (key)
in an array. If the element is present, its index is returned; otherwise, the search reports that the
element is not found.

Types of Searching in Arrays

There are two commonly used searching techniques:

1.​ Linear Search


2.​ Binary Search

1. Linear Search

Linear search is the simplest searching technique. It checks each element of the array one by
one until the required element is found or the array ends.

This method works for both sorted and unsorted arrays.


Algorithm (Linear Search)

1.​ Start from the first element of the array.


2.​ Compare each element with the key.
3.​ If a match is found, return the index.
4.​ If the end of the array is reached, report that the element is not found.

Example

Array: {10, 25, 30, 45, 50}​


Key: 30

Comparisons:

10 ≠ 30
25 ≠ 30
30 = 30 → Found

Time Complexity

●​ Best Case: O(1) (element found at first position)


●​ Worst Case: O(n) (element at last position or not present)
●​ Average Case: O(n)

Space Complexity

●​ O(1)

Advantages

●​ Simple to understand and implement


●​ No requirement for sorted array

Disadvantages

●​ Inefficient for large datasets


2. Binary Search

Description

Binary search is an efficient searching technique that works on sorted arrays only. It repeatedly
divides the search space into half.

Algorithm (Binary Search)

1.​ Set low = 0 and high = n - 1.


2.​ Find mid = (low + high) / 2.
3.​ Compare array[mid] with the key:
○​ If equal, an element is found.
○​ If key < array[mid], search left half.
○​ If key > array[mid], search right half.
4.​ Repeat until the element is found or low > high.

Example

Sorted Array: {10, 20, 30, 40, 50}​


Key: 30

Steps:

mid = 2 → array[2] = 30 → Found

Time Complexity

●​ Best Case: O(1)


●​ Worst Case: O(log n)
●​ Average Case: O(log n)

Space Complexity

●​ Iterative: O(1)
●​ Recursive: O(log n) (due to recursion stack)

Advantages
●​ Very fast for large datasets
●​ Fewer comparisons

Disadvantages

●​ Works only on sorted arrays


●​ Slightly more complex than linear search

Comparison of Linear Search and Binary Search

Feature Linear Search Binary Search

Array Type Sorted / Sorted only


Unsorted

Time Complexity O(n) O(log n)

Simplicity Very simple Moderately complex

Efficiency Low High

1. Iterative Binary Search (C Program)

Program
#include <stdio.h>

int binarySearch(int arr[], int n, int key) {


int low = 0, high = n - 1, mid;

while (low <= high) {


mid = (low + high) / 2;

if (arr[mid] == key)
return mid;
else if (key < arr[mid])
high = mid - 1;
else
low = mid + 1;
}
return -1;
}
int main() {
int arr[50], n, key, i, result;

printf("Enter number of elements: ");


scanf("%d", &n);

printf("Enter elements in sorted order:\n");


for (i = 0; i < n; i++)
scanf("%d", &arr[i]);

printf("Enter element to search: ");


scanf("%d", &key);

result = binarySearch(arr, n, key);

if (result != -1)
printf("Element found at index %d", result);
else
printf("Element not found");

return 0;
}

2. Recursive Binary Search (C Program)

Program
#include <stdio.h>

int binarySearch(int arr[], int low, int high, int key) {


int mid;

if (low <= high) {


mid = (low + high) / 2;

if (arr[mid] == key)
return mid;
else if (key < arr[mid])
return binarySearch(arr, low, mid - 1, key);
else
return binarySearch(arr, mid + 1, high, key);
}
return -1;
}

int main() {
int arr[50], n, key, i, result;

printf("Enter number of elements: ");


scanf("%d", &n);

printf("Enter elements in sorted order:\n");


for (i = 0; i < n; i++)
scanf("%d", &arr[i]);

printf("Enter element to search: ");


scanf("%d", &key);

result = binarySearch(arr, 0, n - 1, key);

if (result != -1)
printf("Element found at index %d", result);
else
printf("Element not found");

return 0;
}

Key Notes

Binary search works only on sorted arrays

●​ Iterative binary search uses a loop and constant space


●​ Recursive binary search uses function calls and extra stack space

Time and Space Complexity

Method Time Complexity Space Complexity

Iterative O(log n) O(1)


Recursiv O(log n) O(log n)
e

Bubble Sort

1. What is Bubble Sort?

Bubble Sort is a simple comparison-based sorting algorithm.​


It repeatedly compares adjacent elements and swaps them if they are in the wrong order.​
With each pass, the largest unsorted element “bubbles up” to its correct position at the end of
the array.

2. Key Idea

●​ Compare two neighboring elements


●​ Swap if the left element is greater than the right
●​ After one full pass, the largest element is placed at the end
●​ Repeat the process for the remaining unsorted part

3. Example for Understanding

Let the array be:

A = [5, 1, 4, 2, 8]
4. Dry Run (Step-by-Step)

Pass 1

Compare adjacent elements:

Comparison Result Array after step

5&1 Swap [1, 5, 4, 2, 8]

5&4 Swap [1, 4, 5, 2, 8]

5&2 Swap [1, 4, 2, 5, 8]

5&8 No [1, 4, 2, 5, 8]
swap

✔ Largest element 8 is now in correct position.

Pass 2

Comparison Result Array

1&4 No [1, 4, 2, 5, 8]
swap

4&2 Swap [1, 2, 4, 5, 8]

4&5 No [1, 2, 4, 5, 8]
swap

✔ Next largest element 5 is fixed.

Pass 3

Comparison Result Array

1&2 No [1, 2, 4, 5, 8]
swap
2&4 No [1, 2, 4, 5, 8]
swap

✔ Array is sorted.

5. Algorithm (Steps)

1.​ Start from the first element


2.​ Compare adjacent elements
3.​ Swap if the left element is greater
4.​ Continue till the end of the array
5.​ Repeat for remaining elements
6.​ Stop when the array is sorted

6. Bubble Sort – C Program


#include <stdio.h>

int main() {
int arr[] = {5, 1, 4, 2, 8};
int n = 5;
int i, j, temp;

for (i = 0; i < n - 1; i++) {


for (j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// swap
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}

printf("Sorted array: ");


for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}

return 0;
}

7. Code Explanation

●​ Outer loop (i)​


Controls the number of passes​
After each pass, one element reaches its correct position
●​ Inner loop (j)​
Compares adjacent elements in the unsorted part
●​ Swap condition​
If arr[j] > arr[j+1], swap them
●​ n - i - 1​
Avoids comparing already sorted elements at the end

8. Time and Space Complexity

Case Time Complexity

Best Case (already O(n) (with optimization)


sorted)

Average Case O(n²)

Worst Case (reverse O(n²)


order)

Space Complexity: O(1) (in-place sorting)

9. Characteristics of Bubble Sort

●​ Simple and easy to understand


●​ Stable sorting algorithm
●​ Not efficient for large datasets
●​ Best suited for learning and small inputs

10. Summary
●​ Bubble Sort repeatedly swaps adjacent elements
●​ Largest element moves to the end in each pass
●​ Uses nested loops
●​ Time complexity is O(n²)
●​ Easy but inefficient for large data

Selection Sort

1. What is Selection Sort?

Selection Sort is a comparison-based sorting algorithm that works by repeatedly selecting the
smallest element from the unsorted portion of the array and placing it at the beginning.

Unlike Bubble Sort, Selection Sort makes minimum swaps.

2. Key Idea

●​ Divide the array into sorted and unsorted parts


●​ Initially, the sorted part is empty
●​ Find the minimum element in the unsorted part
●​ Swap it with the first element of the unsorted part
●​ Move the boundary of the sorted part one step forward

3. Example for Understanding

Let the array be:

A = [64, 25, 12, 22, 11]

4. Dry Run (Step-by-Step)

Pass 1

Unsorted part: [64, 25, 12, 22, 11]​


Minimum element = 11
Swap 64 and 11:

[11, 25, 12, 22, 64]

✔ First element is now sorted

Pass 2

Unsorted part: [25, 12, 22, 64]​


Minimum element = 12

Swap 25 and 12:

[11, 12, 25, 22, 64]

✔ First two elements are sorted

Pass 3

Unsorted part: [25, 22, 64]​


Minimum element = 22

Swap 25 and 22:

[11, 12, 22, 25, 64]

Pass 4

Unsorted part: [25, 64]​


Minimum element = 25

No swap required

✔ Array is sorted

5. Algorithm (Steps)
1.​ Start from index 0
2.​ Assume the first unsorted element is the minimum
3.​ Compare it with the remaining elements
4.​ If a smaller element is found, update the minimum index
5.​ Swap the minimum element with the first unsorted element
6.​ Repeat for the remaining array

6. Selection Sort – C Program


#include <stdio.h>

int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = 5;
int i, j, minIndex, temp;

for (i = 0; i < n - 1; i++) {


minIndex = i;

for (j = i + 1; j < n; j++) {


if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}

// Swap the found minimum element


temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}

printf("Sorted array: ");


for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}

return 0;
}

7. Code Explanation
●​ Outer loop (i)​
Marks the beginning of the unsorted part
●​ minIndex​
Stores the index of the smallest element
●​ Inner loop (j)​
Searches for the minimum element in the unsorted part
●​ Swap operation​
Places the smallest element at its correct position

8. Time and Space Complexity

Case Time Complexity

Best Case O(n²)

Average O(n²)
Case

Worst Case O(n²)

Space Complexity: O(1) (In-place)

9. Characteristics of Selection Sort

●​ Simple and easy to implement


●​ Performs fewer swaps than Bubble Sort
●​ Not a stable sorting algorithm (in general form)
●​ Inefficient for large datasets

10. Bubble Sort vs Selection Sort

Feature Bubble Sort Selection Sort

Swaps Many Very few

Comparison Many Many


s

Stability Stable Not stable


Efficiency Low Low

11. Summary (For Exams)

●​ Selection Sort selects the minimum element


●​ Sorted and unsorted sections are maintained
●​ Time complexity is O(n²)
●​ Suitable for small datasets and learning

Below is a complete, exam-ready explanation of Insertion Sort, written clearly for DSA / C
programming students.

Insertion Sort

Definition

Insertion sort is a comparison-based sorting algorithm that sorts an array by taking one element
at a time and inserting it into its correct position in the already sorted part of the array.

It works in a way similar to arranging playing cards in hand.

Working Principle

●​ The array is divided into two parts:


○​ Sorted part (left side)
○​ Unsorted part (right side)
●​ Initially, the first element is considered sorted.
●​ Each next element is picked and placed at the correct position in the sorted part by
shifting elements.

Algorithm (Insertion Sort)

1.​ Start from the second element of the array (index 1).
2.​ Store the current element as key.
3.​ Compare key with elements before it.
4.​ Shift all elements greater than key one position to the right.
5.​ Insert key at its correct position.
6.​ Repeat until the array is sorted.

C Program for Insertion Sort

#include <stdio.h>

int main() {

int arr[50], n, i, j, key;

printf("Enter number of elements: ");

scanf("%d", &n);

printf("Enter array elements:\n");

for (i = 0; i < n; i++)

scanf("%d", &arr[i]);

for (i = 1; i < n; i++) {

key = arr[i];

j = i - 1;

while (j >= 0 && arr[j] > key) {

arr[j + 1] = arr[j];

j--;

}
arr[j + 1] = key;

printf("Sorted array:\n");

for (i = 0; i < n; i++)

printf("%d ", arr[i]);

return 0;

Dry Run

Input

Array = {8, 3, 5, 2}

Pass 1 (i = 1, key = 3)

8 > 3 → shift 8

Insert 3

Array: {3, 8, 5, 2}

Pass 2 (i = 2, key = 5)

8 > 5 → shift 8

Insert 5

Array: {3, 5, 8, 2}
Pass 3 (i = 3, key = 2)

8 > 2 → shift

5 > 2 → shift

3 > 2 → shift

Insert 2

Array: {2, 3, 5, 8}

Given Array

{4, 3, 5, 2, 1}

Insertion sort starts from index 1 because the first element is assumed to be already sorted.

Initial State

Sorted part: {4}

Unsorted part: {3, 5, 2, 1}

Pass 1 (i = 1)

Key = 3​
Compare with elements to the left.

4 > 3 → shift 4 to the right

Insert 3 at index 0
Array after Pass 1

{3, 4, 5, 2, 1}

Pass 2 (i = 2)

Key = 5​
Compare with elements to the left.

4 < 5 → no shift needed

Array after Pass 2

{3, 4, 5, 2, 1}

Pass 3 (i = 3)

Key = 2​
Compare with elements to the left.

5 > 2 → shift 5

4 > 2 → shift 4

3 > 2 → shift 3

Insert 2 at index 0

Array after Pass 3

{2, 3, 4, 5, 1}
Pass 4 (i = 4)

Key = 1​
Compare with elements to the left.

5 > 1 → shift 5

4 > 1 → shift 4

3 > 1 → shift 3

2 > 1 → shift 2

Insert 1 at index 0

Array after Pass 4

{1, 2, 3, 4, 5}

Final Sorted Array

{1, 2, 3, 4, 5}

Quick Pass

Pas Key Array State


s

1 3 {3, 4, 5, 2, 1}
2 5 {3, 4, 5, 2, 1}

3 2 {2, 3, 4, 5, 1}

4 1 {1, 2, 3, 4, 5}

Key Observation

●​ Maximum shifting happens in Pass 3 and Pass 4


●​ This input is close to the worst case
●​ Time Complexity here approaches O(n²)

Time Complexity

Case Time Complexity

Best Case (Already sorted) O(n)

Average Case O(n²)

Worst Case (Reverse O(n²)


order)

Space Complexity

●​ O(1) (In-place sorting)


Advantages

●​ Simple and easy to implement


●​ Efficient for small datasets
●​ Stable sorting algorithm
●​ Adaptive (fast for nearly sorted arrays)

Disadvantages

●​ Inefficient for large datasets


●​ Slower compared to algorithms like Merge Sort or Quick Sort

Real-World Example

Sorting playing cards in hand:

●​ Pick one card at a time


●​ Insert it in the correct position among already sorted cards

Insertion sort sorts elements by repeatedly inserting each element into its correct position in the
sorted part of the array.

You might also like