Data Structures & Algorithms โ€“ University Level โ€“ Pak Notes Hub
๐Ÿ“Š University Level โ€” BS CS / BS IT

Data Structures &
Algorithms Complete Notes

Arrays ยท Linked Lists ยท Trees ยท Graphs ยท Sorting ยท Searching ยท Dynamic Programming โ€” Master DSA in Easy English

Time Complexity
Space Complexity
Algorithm Design
Unit 1

Basics & Time Complexity

Foundation of Data Structures and Algorithm Analysis

What is a Data Structure?

A data structure is a way to organize, store, and manage data efficiently. Different data structures are optimized for different operations.

๐Ÿ’ก Think of it like choosing between a library card catalog (fast lookup), a shelf (sequential access), or a filing cabinet (organized groups).

Why Study DSA?

  • Write faster and more efficient code
  • Pass technical interviews (DSA is 70% of coding interviews)
  • Understand how databases, OS, and compilers work
  • Optimize applications for scale

Big O Notation โ€“ Time Complexity

Big O describes the worst-case runtime as input size grows. It ignores constants and lower-order terms.

NotationNameExample OperationsSpeed
O(1)ConstantArray access by index, hash lookupโšก Excellent
O(log n)LogarithmicBinary searchโœ“ Great
O(n)LinearSimple loop, linear searchโ‰ˆ Good
O(n log n)LinearithmicMerge sort, quick sortโš  Fair
O(nยฒ)QuadraticBubble sort, nested loopsโœ— Bad
O(nยณ)CubicTriple nested loopsโœ— Worse
O(2โฟ)ExponentialRecursion without memoizationโœ—โœ— Terrible
O(n!)FactorialPermutationsโœ—โœ—โœ— Impossible

Calculating Time Complexity

// Example 1: O(1) - Constant
int getFirst(int[] arr) {
    return arr[0];  // Always 1 operation, regardless of array size
}

// Example 2: O(n) - Linear
void printAll(int[] arr) {
    for(int i = 0; i < arr.length; i++) {  // Loop runs n times
        System.out.println(arr[i]);
    }
}

// Example 3: O(nยฒ) - Quadratic
void bubbleSort(int[] arr) {
    for(int i = 0; i < arr.length; i++) {          // Outer loop: n times
        for(int j = 0; j < arr.length-1; j++) { // Inner loop: n times
            // n ร— n = O(nยฒ)
        }
    }
}

Space Complexity

Space complexity measures the extra memory used by an algorithm (not counting input).

// O(1) space - only uses fixed variables
int sum(int[] arr) {
    int total = 0;  // Just 1 variable
    for(int x : arr) total += x;
    return total;
}

// O(n) space - creates new array
int[] duplicate(int[] arr) {
    int[] copy = new int[arr.length];  // New array of size n
    System.arraycopy(arr, 0, copy, 0, arr.length);
    return copy;
}
โœ๏ธ Practice: What is the time complexity of: (a) Finding max in unsorted array (b) Binary search (c) Accessing element at index 5
Unit 2

Arrays & Strings

Fundamental Data Structures with Contiguous Memory

Array Basics

An array is a fixed-size collection of elements stored in contiguous memory. Fast access but slow insertion/deletion.

OperationTime ComplexityNotes
Access elementO(1)Direct memory access via index
Search (unsorted)O(n)Must check each element
Search (sorted)O(log n)Binary search
Insert at endO(1)If space available
Insert at middleO(n)Shift remaining elements
DeleteO(n)Shift remaining elements

2D Arrays (Matrices)

A 2D array is an array of arrays. Think of it as a grid with rows and columns.

// 2D array declaration and access
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// Access element at row 1, column 2
int value = matrix[1][2];  // Returns 6

// Traverse 2D array
for(int i = 0; i < matrix.length; i++) {
    for(int j = 0; j < matrix[i].length; j++) {
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}

Common Array Problems

Two Pointer Technique: Use two pointers moving in opposite or same direction to solve problems efficiently.
// Find if array is sorted
boolean isSorted(int[] arr) {
    for(int i = 0; i < arr.length - 1; i++) {
        if(arr[i] > arr[i+1]) return false;
    }
    return true;
}

// Reverse array using two pointers
void reverse(int[] arr) {
    int left = 0, right = arr.length - 1;
    while(left < right) {
        // Swap
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
        left++;
        right--;
    }
}

String Manipulation

Strings are arrays of characters. Many array techniques apply to strings.

// Check if palindrome
boolean isPalindrome(String s) {
    int left = 0, right = s.length() - 1;
    while(left < right) {
        if(s.charAt(left) != s.charAt(right)) {
            return false;
        }
        left++;
        right--;
    }
    return true;
}

// Reverse string
String reverse(String s) {
    char[] chars = s.toCharArray();
    int left = 0, right = chars.length - 1;
    while(left < right) {
        char temp = chars[left];
        chars[left] = chars[right];
        chars[right] = temp;
        left++;
        right--;
    }
    return new String(chars);
}
โœ๏ธ Practice: (a) Find max element in array (b) Count occurrences of element (c) Rotate array by k positions
Unit 3

Linked Lists

Dynamic Data Structure with Non-Contiguous Memory

Linked List Basics

A linked list is a dynamic collection where elements (nodes) are linked via pointers. Unlike arrays, it uses non-contiguous memory.

// Node structure
class Node {
    int data;
    Node next;
    
    Node(int data) {
        this.data = data;
        this.next = null;
    }
}

// Simple linked list
class LinkedList {
    Node head;
    
    // Insert at beginning - O(1)
    void insertFirst(int data) {
        Node newNode = new Node(data);
        newNode.next = head;
        head = newNode;
    }
}

Linked List Operations

OperationTimeSpaceNotes
AccessO(n)O(1)Must traverse from head
SearchO(n)O(1)Linear search
Insert at headO(1)O(1)Very fast
Insert at tailO(n)O(1)Need to find tail
Delete at headO(1)O(1)Very fast
Delete at tailO(n)O(1)Need previous node

Traversal & Display

// Display all elements
void display() {
    Node current = head;
    while(current != null) {
        System.out.print(current.data + " โ†’ ");
        current = current.next;
    }
    System.out.println("null");
}

Doubly Linked List

Each node has pointers to both next AND previous nodes. Allows backward traversal.

// Doubly linked list node
class DNode {
    int data;
    DNode next, prev;
    
    DNode(int data) {
        this.data = data;
        this.next = this.prev = null;
    }
}

Circular Linked List

The last node points back to the first node, forming a circle. No null at the end.

๐Ÿ’ก Use cases: Round-robin scheduling, music playlists, carousel components
โœ๏ธ Practice: (a) Find length of linked list (b) Reverse a linked list (c) Find middle element
Unit 4

Stack & Queue

Specialized Data Structures with Restricted Access Patterns

Stack (LIFO โ€“ Last In First Out)

Think of a stack of plates. You add and remove from the same end (top). Last plate added is first one removed.

OperationTimeDescription
Push (add)O(1)Add element to top
Pop (remove)O(1)Remove from top
Peek (view)O(1)View top without removing
isEmptyO(1)Check if empty
// Stack implementation
class Stack {
    private int[] items;
    private int top = -1;
    
    Stack(int capacity) {
        items = new int[capacity];
    }
    
    void push(int value) {
        items[++top] = value;
    }
    
    int pop() {
        return items[top--];
    }
    
    int peek() {
        return items[top];
    }
    
    boolean isEmpty() {
        return top == -1;
    }
}

Stack Applications

  • Browser history: Back button uses stack
  • Undo/Redo: All editors use stacks
  • Function calls: Call stack in programming
  • Expression evaluation: Check balanced parentheses
  • Parsing: Compilers use stacks
// Check balanced parentheses using stack
boolean isBalanced(String s) {
    Stack<Character> st = new Stack<>();
    
    for(char c : s.toCharArray()) {
        if(c == '(' || c == '[' || c == '{') {
            st.push(c);
        } else if(c == ')' || c == ']' || c == '}') {
            if(st.isEmpty()) return false;
            st.pop();
        }
    }
    
    return st.isEmpty();
}

Queue (FIFO โ€“ First In First Out)

Think of a queue at a movie theater. You add at the back (rear) and remove from front. First person in is first served.

OperationTimeDescription
EnqueueO(1)Add to rear
DequeueO(1)Remove from front
PeekO(1)View front element

Queue Applications

  • CPU scheduling: Process queue
  • Printer queue: Print jobs in order
  • BFS graph traversal: Level-order traversal
  • Message queues: Kafka, RabbitMQ

Priority Queue

Elements are removed based on priority, not just insertion order. Uses a heap internally.

๐Ÿ’ก Example: Hospital emergency room. Critical patients served before minor injuries, regardless of arrival order.
โœ๏ธ Practice: (a) Implement stack using queue (b) Implement queue using stack (c) Reverse a queue
Unit 5

Trees

Hierarchical Data Structure for Organizing Information

Tree Basics

A tree is a hierarchical data structure with a root node and child nodes. It's a connected graph with no cycles.

       A (root)
      /|\
     B C D
    /|   |
   E F   G

Terminology:
- Root: Top node (A)
- Parent: Node with children (A is parent of B, C, D)
- Children: Nodes under a parent (B, C are children of A)
- Leaf: Node with no children (E, F, G)
- Subtree: Tree below any node
- Height: Distance from node to deepest leaf
- Depth: Distance from root to node

Binary Tree

Each node has at most 2 children (left and right).

// Binary tree node
class TreeNode {
    int data;
    TreeNode left, right;
    
    TreeNode(int data) {
        this.data = data;
    }
}

Tree Traversals

Four main ways to visit all nodes:

TraversalOrderExample (see diagram)Use Case
InorderLeft โ†’ Root โ†’ RightE, B, F, A, C, G, DBST (sorted output)
PreorderRoot โ†’ Left โ†’ RightA, B, E, F, C, D, GCopy tree, prefix notation
PostorderLeft โ†’ Right โ†’ RootE, F, B, C, G, D, ADelete tree
Level OrderLevel by levelA, B, C, D, E, F, GBFS
// Inorder traversal (recursive)
void inorder(TreeNode root) {
    if(root == null) return;
    inorder(root.left);
    System.out.print(root.data + " ");
    inorder(root.right);
}

// Level order traversal (using queue for BFS)
void levelOrder(TreeNode root) {
    Queue<TreeNode> q = new LinkedList<>();
    q.add(root);
    
    while(!q.isEmpty()) {
        TreeNode node = q.poll();
        System.out.print(node.data + " ");
        
        if(node.left != null) q.add(node.left);
        if(node.right != null) q.add(node.right);
    }
}

Tree Properties

  • Perfect Binary Tree: All levels completely filled
  • Complete Binary Tree: All levels filled except possibly the last
  • Balanced Binary Tree: Height difference โ‰ค 1 for all subtrees
  • Full Binary Tree: Every node has 0 or 2 children
โœ๏ธ Practice: (a) Find height of tree (b) Count total nodes (c) Find sum of all nodes
Unit 6

Binary Search Trees

Ordered Trees for Efficient Searching

BST Property

A Binary Search Tree is a binary tree where:

  • Left subtree has values smaller than root
  • Right subtree has values greater than root
  • Both left and right subtrees are also BSTs

BST Operations

OperationBest CaseWorst CaseNotes
SearchO(log n)O(n)Worst if tree is skewed
InsertO(log n)O(n)Always at leaf
DeleteO(log n)O(n)Complex if node has 2 children
Inorder TraversalO(n)O(n)Gives sorted output
// BST Search
TreeNode search(TreeNode root, int key) {
    if(root == null) return null;
    
    if(key == root.data) return root;
    else if(key < root.data) return search(root.left, key);
    else return search(root.right, key);
}

// BST Insert
TreeNode insert(TreeNode root, int value) {
    if(root == null) return new TreeNode(value);
    
    if(value < root.data) {
        root.left = insert(root.left, value);
    } else if(value > root.data) {
        root.right = insert(root.right, value);
    }
    
    return root;
}

BST Delete โ€“ 3 Cases

  • Node is leaf: Simply remove it
  • Node has 1 child: Replace with its child
  • Node has 2 children: Replace with inorder successor (smallest in right subtree), then delete successor

Balanced BSTs โ€“ AVL & Red-Black Trees

Regular BSTs can become skewed. Balanced trees ensure O(log n) for all operations.

๐Ÿ’ก AVL Tree: Height difference โ‰ค 1. Rotations keep it balanced. Red-Black Tree: Used in Java HashMap, C++ map.
โœ๏ธ Practice: (a) Check if tree is BST (b) Find kth smallest element (c) Find LCA (Lowest Common Ancestor)
Unit 7

Heaps & Priority Queues

Complete Binary Trees with Heap Property

Heap Property

A heap is a complete binary tree where each parent is greater (max heap) or smaller (min heap) than its children.

  • Max Heap: Parent โ‰ฅ Children. Root is maximum.
  • Min Heap: Parent โ‰ค Children. Root is minimum.
  • Complete Binary Tree: All levels filled except possibly last, which is left-aligned.

Heap Operations

OperationTimeDescription
InsertO(log n)Add at end, bubble up
Delete Min/MaxO(log n)Remove root, move last to root, bubble down
Peek Min/MaxO(1)View root
HeapifyO(n)Build heap from array
// Min Heap using array
class MinHeap {
    private int[] heap;
    private int size = 0;
    
    // Parent: (i-1)/2, Left: 2i+1, Right: 2i+2
    
    void insert(int value) {
        heap[size] = value;
        bubbleUp(size);
        size++;
    }
    
    void bubbleUp(int index) {
        while(index > 0) {
            int parent = (index - 1) / 2;
            if(heap[index] < heap[parent]) {
                // Swap
                int temp = heap[index];
                heap[index] = heap[parent];
                heap[parent] = temp;
                index = parent;
            } else break;
        }
    }
}

Heap Applications

  • Priority Queue: Process elements by priority
  • Dijkstra's algorithm: Shortest path
  • Heap Sort: Efficient sorting O(n log n)
  • Top K elements: Find k largest/smallest efficiently
โœ๏ธ Practice: (a) Implement max heap (b) Implement heap sort (c) Find Kth largest element
Unit 8

Graphs

Non-Linear Data Structure for Connected Data

Graph Basics

A graph consists of vertices (nodes) and edges (connections). Can be directed or undirected, weighted or unweighted.

// Types of Graphs:
1. Directed (Digraph): Aโ†’B (one direction)
2. Undirected: Aโ€”B (both directions)
3. Weighted: Edge has a value/cost
4. Unweighted: All edges equal

// Density:
- Sparse: Few edges (n ~ m, where m is edges)
- Dense: Many edges (m ~ nยฒ)

Graph Representations

RepresentationSpaceAdd EdgeCheck Edge
Adjacency MatrixO(Vยฒ)O(1)O(1)
Adjacency ListO(V+E)O(1)O(E)
Edge ListO(E)O(1)O(E)
// Adjacency List representation
Map<Integer, List<Integer>> graph = new HashMap<>();

// Add edge from u to v
void addEdge(int u, int v) {
    graph.putIfAbsent(u, new ArrayList<>());
    graph.get(u).add(v);
}

Graph Traversals

BFS (Breadth-First Search): Level by level. Uses queue. O(V + E) time. Finds shortest path in unweighted graph.
DFS (Depth-First Search): Go deep first. Uses stack/recursion. O(V + E) time. Finds connected components, detect cycles.
// BFS Traversal
void bfs(int start) {
    Queue<Integer> q = new LinkedList<>();
    Set<Integer> visited = new HashSet<>();
    
    q.add(start);
    visited.add(start);
    
    while(!q.isEmpty()) {
        int node = q.poll();
        System.out.print(node + " ");
        
        for(int neighbor : graph.getOrDefault(node, new ArrayList<>())) {
            if(!visited.contains(neighbor)) {
                visited.add(neighbor);
                q.add(neighbor);
            }
        }
    }
}

// DFS Traversal (Recursive)
void dfs(int node, Set<Integer> visited) {
    visited.add(node);
    System.out.print(node + " ");
    
    for(int neighbor : graph.getOrDefault(node, new ArrayList<>())) {
        if(!visited.contains(neighbor)) {
            dfs(neighbor, visited);
        }
    }
}

Important Graph Algorithms

  • Dijkstra: Shortest path (weighted, non-negative)
  • Bellman-Ford: Shortest path (handles negative weights)
  • Floyd-Warshall: All pairs shortest path
  • Kruskal/Prim: Minimum Spanning Tree
  • Topological Sort: DAG ordering
โœ๏ธ Practice: (a) Detect cycle in graph (b) Find connected components (c) Topological sort
Unit 9

Sorting Algorithms

Methods to Arrange Elements in Order

Sorting Comparison

AlgorithmBestAverageWorstSpaceStable
Bubble SortO(n)O(nยฒ)O(nยฒ)O(1)โœ“
Selection SortO(nยฒ)O(nยฒ)O(nยฒ)O(1)โœ—
Insertion SortO(n)O(nยฒ)O(nยฒ)O(1)โœ“
Merge SortO(n log n)O(n log n)O(n log n)O(n)โœ“
Quick SortO(n log n)O(n log n)O(nยฒ)O(log n)โœ—
Heap SortO(n log n)O(n log n)O(n log n)O(1)โœ—

Bubble Sort โ€“ O(nยฒ)

Repeatedly swap adjacent elements if they're in wrong order. Simplest but slowest.

// Bubble Sort
void bubbleSort(int[] arr) {
    int n = arr.length;
    
    for(int i = 0; i < n - 1; i++) {
        // Last i elements are already sorted
        for(int j = 0; j < n - i - 1; j++) {
            if(arr[j] > arr[j + 1]) {
                // Swap
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

Quick Sort โ€“ O(n log n) average

Divide-and-conquer. Pick pivot, partition, recursively sort. Fastest in practice.

// Quick Sort
void quickSort(int[] arr, int low, int high) {
    if(low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

int partition(int[] arr, int low, int high) {
    int pivot = arr[high];
    int i = low - 1;
    
    for(int j = low; j < high; j++) {
        if(arr[j] < pivot) {
            i++;
            // Swap arr[i] and arr[j]
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    
    // Swap arr[i+1] and arr[high]
    int temp = arr[i + 1];
    arr[i + 1] = arr[high];
    arr[high] = temp;
    
    return i + 1;
}

Merge Sort โ€“ O(n log n) guaranteed

Divide-and-conquer. Divide array in half, recursively sort, merge. Stable and predictable.

// Merge Sort
void mergeSort(int[] arr, int left, int right) {
    if(left < right) {
        int mid = left + (right - left) / 2;
        mergeSort(arr, left, mid);
        mergeSort(arr, mid + 1, right);
        merge(arr, left, mid, right);
    }
}
โœ๏ธ Practice: (a) Implement insertion sort (b) Find median of two sorted arrays (c) Sort array of 0s, 1s, 2s (Dutch Flag)
Unit 10

Searching Algorithms

Methods to Find Elements Efficiently

Linear Search โ€“ O(n)

Check each element one by one. Works on unsorted arrays.

// Linear Search
int linearSearch(int[] arr, int target) {
    for(int i = 0; i < arr.length; i++) {
        if(arr[i] == target) {
            return i;
        }
    }
    return -1;  // Not found
}

Binary Search โ€“ O(log n)

Eliminate half the remaining elements each time. Requires sorted array. Much faster for large data.

// Binary Search (Iterative)
int binarySearch(int[] arr, int target) {
    int left = 0, right = arr.length - 1;
    
    while(left <= right) {
        int mid = left + (right - left) / 2;
        
        if(arr[mid] == target) {
            return mid;
        } else if(arr[mid] < target) {
            left = mid + 1;  // Search right half
        } else {
            right = mid - 1;  // Search left half
        }
    }
    
    return -1;  // Not found
}

// Binary Search (Recursive)
int binarySearchRec(int[] arr, int target, int left, int right) {
    if(left > right) return -1;
    
    int mid = left + (right - left) / 2;
    
    if(arr[mid] == target) return mid;
    else if(arr[mid] < target) return binarySearchRec(arr, target, mid + 1, right);
    else return binarySearchRec(arr, target, left, mid - 1);
}

Search Comparison

AlgorithmTimeSpaceRequires Sorting
Linear SearchO(n)O(1)No
Binary SearchO(log n)O(1)Yes
Hash LookupO(1) avgO(n)No

Binary Search Variations

  • Find first occurrence: Search left half even if found
  • Find last occurrence: Search right half even if found
  • Find smallest โ‰ฅ target: Lower bound
  • Find largest โ‰ค target: Upper bound
โœ๏ธ Practice: (a) Find first and last position of element (b) Search in rotated sorted array (c) Find peak element
Unit 11

Dynamic Programming

Optimization Technique Breaking Problems into Overlapping Subproblems

What is Dynamic Programming?

DP solves problems by breaking them into overlapping subproblems and storing results (memoization) to avoid recomputation.

๐Ÿ’ก Two conditions for DP: (1) Optimal substructure (2) Overlapping subproblems

Fibonacci Sequence โ€“ Classic Example

// Naive Recursion โ€“ EXPONENTIAL O(2โฟ) โ€“ VERY SLOW
int fib(int n) {
    if(n <= 1) return n;
    return fib(n-1) + fib(n-2);  // Recomputes same values!
}

// DP with Memoization โ€“ O(n) โ€“ MUCH FASTER
int fib(int n, int[] memo) {
    if(n <= 1) return n;
    if(memo[n] != 0) return memo[n];  // Return cached result
    
    memo[n] = fib(n-1, memo) + fib(n-2, memo);
    return memo[n];
}

// DP with Tabulation (bottom-up) โ€“ O(n) โ€“ BEST
int fib(int n) {
    int[] dp = new int[n+1];
    dp[0] = 0; dp[1] = 1;
    
    for(int i = 2; i <= n; i++) {
        dp[i] = dp[i-1] + dp[i-2];
    }
    
    return dp[n];
}

0/1 Knapsack Problem

Given items with weight and value, fill knapsack of capacity W to maximize value.

// 0/1 Knapsack using DP
int knapsack(int[] weights, int[] values, int W) {
    int n = weights.length;
    int[][] dp = new int[n+1][W+1];
    
    // dp[i][w] = max value with first i items and capacity w
    
    for(int i = 1; i <= n; i++) {
        for(int w = 1; w <= W; w++) {
            if(weights[i-1] <= w) {
                // Include or exclude item
                dp[i][w] = Math.max(
                    values[i-1] + dp[i-1][w-weights[i-1]],  // Include
                    dp[i-1][w]                               // Exclude
                );
            } else {
                dp[i][w] = dp[i-1][w];  // Can't include
            }
        }
    }
    
    return dp[n][W];
}

Common DP Problems

  • Longest Common Subsequence (LCS): O(mร—n)
  • Edit Distance: O(mร—n)
  • Coin Change: O(nร—W)
  • Maximum Subarray Sum: O(n)
  • Rod Cutting: O(nยฒ)
โœ๏ธ Practice: (a) Longest increasing subsequence (b) Longest palindromic subsequence (c) House robber problem
Unit 12

Greedy Algorithms

Making Locally Optimal Choices for Global Solution

Greedy Approach

Greedy algorithms make the best choice at each step, hoping to find a global optimum. Fast but not always optimal.

๐Ÿ’ก Greedy works when problem has "greedy choice property" โ€“ local optimum = global optimum. Example: Dijkstra, Huffman coding.

Activity Selection Problem

Select maximum non-overlapping activities.

// Activity Selection โ€“ Greedy approach
void activitySelection(List<Activity> activities) {
    // Sort by finish time
    activities.sort((a, b) -> a.finish - b.finish);
    
    List<Activity> selected = new ArrayList<>();
    selected.add(activities.get(0));
    int lastFinish = activities.get(0).finish;
    
    for(int i = 1; i < activities.size(); i++) {
        if(activities.get(i).start >= lastFinish) {
            selected.add(activities.get(i));
            lastFinish = activities.get(i).finish;
        }
    }
    
    System.out.println("Selected " + selected.size() + " activities");
}

Huffman Coding

Assign variable-length codes based on character frequency. More frequent โ†’ shorter code.

๐Ÿ’ก Used in compression (ZIP, JPEG). Saves space by using fewer bits for common characters.

Fractional Knapsack

Unlike 0/1 knapsack, you can take fractional items. Greedy works here!

// Greedy approach: Take items by value/weight ratio
double knapsack(int[] values, int[] weights, int W) {
    // Sort by value/weight ratio in descending order
    // Take items greedily until capacity full
}
Time Complexity: O(n log n) due to sorting

Greedy Problems

  • Coin Change (minimum coins): O(n log n)
  • Interval Scheduling: O(n log n)
  • Job Sequencing: O(n log n)
  • Minimum Spanning Tree (Kruskal/Prim): O(E log V)
โœ“ When Greedy Fails: 0/1 Knapsack โ€“ greedy by value/weight ratio doesn't work. Must use DP!
โœ๏ธ Practice: (a) Implement coin change with minimum coins (b) Gas station problem (c) Jump game

๐ŸŽ‰ Congratulations!

You've completed the comprehensive DSA course! Now practice these concepts on LeetCode, HackerRank, or CodeSignal.

๐Ÿ“‹

Quick Reference โ€“ Time Complexities

Bookmark this for quick lookup during coding

Data Structure / OperationBestAverageWorst
Array AccessO(1)O(1)O(1)
Linked List SearchO(1)O(n)O(n)
Binary Search Tree SearchO(log n)O(log n)O(n)
Hash Table InsertO(1)O(1)O(n)
Heap Insert/DeleteO(log n)O(log n)O(log n)
Graph BFS/DFSO(V+E)O(V+E)O(V+E)
Merge SortO(n log n)O(n log n)O(n log n)
Quick SortO(n log n)O(n log n)O(nยฒ)

๐Ÿ“š Pak Notes Hub โ€” DSA Complete Notes | University Level | BS CS / BS IT
For corrections and suggestions: support@paknoteshub.com