Sorting Algos and Patterns - (Theory)

Sorting Algorithms - TC and SC (Concept)

This includes:


Introduction to Sorting

Sorting is the process of rearranging data in a specific order (typically ascending or descending). Sorting is fundamental in programming because many algorithms (binary search, interval merge, greedy strategies) depend on sorted data to function correctly.


1. Bubble Sort

Concept:

Repeatedly compares adjacent elements and swaps them if they are in the wrong order. After each pass, the largest unsorted element "bubbles up" to its correct position.

Dry Run:

Input: [5, 3, 1, 4, 2]

Done.

Time Complexity:

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

Real-life Analogy:

Like bubbles rising to the surface in a liquid — each biggest element rises to its correct place at the end.

Java Code:

void bubbleSort(int[] arr) {
    int n = arr.length;
    boolean swapped;
    for (int i = 0; i < n - 1; i++) {
        swapped = false;
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                swapped = true;
            }
        }
        if (!swapped) break;
    }
}

2. Selection Sort

Concept:

Finds the smallest element in the unsorted portion and places it in its correct position by swapping.

Dry Run:

Input: [5, 3, 1, 4, 2]

Time Complexity:

Space Complexity: O(1)

Real-life Analogy:

Like choosing the best player in a draft from the remaining pool each time.

Java Code:

void selectionSort(int[] arr) {
    int n = arr.length;
    for (int i = 0; i < n - 1; i++) {
        int minIdx = i;
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIdx]) {
                minIdx = j;
            }
        }
        int temp = arr[minIdx];
        arr[minIdx] = arr[i];
        arr[i] = temp;
    }
}

3. Insertion Sort

Concept:

Builds the sorted array by picking one element at a time and inserting it into the correct position in the already sorted portion.

Dry Run:

Input: [5, 3, 1, 4, 2]

Time Complexity:

Space Complexity: O(1)

Real-life Analogy:

Like sorting playing cards in your hand.

Java Code:

void insertionSort(int[] arr) {
    for (int i = 1; i < arr.length; i++) {
        int key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
}

Comparison Table

Algorithm Best Case Avg Case Worst Case Space Stable Use Case
Bubble Sort O(n) O(n²) O(n²) O(1) Yes Teaching
Selection Sort O(n²) O(n²) O(n²) O(1) No Minimize swaps
Insertion Sort O(n) O(n²) O(n²) O(1) Yes Nearly sorted arrays

Why Inbuilt sort() Is More Effective

Java Arrays.sort():

Python sort():

Benefits:


Problem-Solving Scenarios (Patterns with Code)

1. Sort + Two Pointers

Problem: Find if two numbers sum to a target

boolean hasPairWithSum(int[] arr, int target) {
    Arrays.sort(arr);
    int i = 0, j = arr.length - 1;
    while (i < j) {
        int sum = arr[i] + arr[j];
        if (sum == target) return true;
        else if (sum < target) i++;
        else j--;
    }
    return false;
}

2. Sort + Binary Search

Problem: Check if target exists

boolean contains(int[] arr, int target) {
    Arrays.sort(arr);
    int l = 0, r = arr.length - 1;
    while (l <= r) {
        int mid = l + (r - l) / 2;
        if (arr[mid] == target) return true;
        else if (arr[mid] < target) l = mid + 1;
        else r = mid - 1;
    }
    return false;
}

3. Kth Smallest Element

Problem: Return the kth smallest element

int kthSmallest(int[] arr, int k) {
    Arrays.sort(arr);
    return arr[k - 1];
}

4. Greedy Algorithm

Problem: Activity selection (maximum non-overlapping meetings)

class Meeting {
    int start, end;
    Meeting(int s, int e) { start = s; end = e; }
}

int maxMeetings(List<Meeting> meetings) {
    meetings.sort((a, b) -> a.end - b.end);
    int count = 0, lastEnd = -1;
    for (Meeting m : meetings) {
        if (m.start > lastEnd) {
            count++;
            lastEnd = m.end;
        }
    }
    return count;
}

5. Interval Scheduling (Merge Intervals)

class Interval {
    int start, end;
    Interval(int s, int e) { start = s; end = e; }
}

List<Interval> merge(List<Interval> intervals) {
    intervals.sort((a, b) -> a.start - b.start);
    List<Interval> result = new ArrayList<>();
    Interval prev = intervals.get(0);
    for (int i = 1; i < intervals.size(); i++) {
        Interval curr = intervals.get(i);
        if (curr.start <= prev.end) {
            prev.end = Math.max(prev.end, curr.end);
        } else {
            result.add(prev);
            prev = curr;
        }
    }
    result.add(prev);
    return result;
}

6. Duplicate Removal / Grouping

Problem: Group anagrams

List<List<String>> groupAnagrams(String[] strs) {
    Map<String, List<String>> map = new HashMap<>();
    for (String s : strs) {
        char[] chars = s.toCharArray();
        Arrays.sort(chars);
        String sorted = new String(chars);
        map.computeIfAbsent(sorted, k -> new ArrayList<>()).add(s);
    }
    return new ArrayList<>(map.values());
}

Conclusion