DATA STRUCTURES & ALGORITHMS – FULL COURSE NOTES

Below is a complete, self-contained DSA course note set with every code example in both C++ and Python, organized by modules. All code is tested, concise, and production-ready for interviews (LeetCode-style).

DATA STRUCTURES & ALGORITHMS – FULL COURSE NOTES With C++ & Python Code Examples

DATA STRUCTURES & ALGORITHMS – FULL COURSE NOTES With C++ & Python Code Examples

Below is a complete, self-contained DSA course note set with every code example in both C++ and Python, organized by modules.
All code is tested, concise, and production-ready for interviews (LeetCode-style).


DATA STRUCTURES & ALGORITHMS – FULL COURSE NOTES

With C++ & Python Code Examples


MODULE 0 – COMPLEXITY ANALYSIS

Notation Meaning
O(f(n)) Upper bound
Ω(f(n)) Lower bound
Θ(f(n)) Tight bound

Master Theorem

For T(n) = aT(n/b) + f(n):

If f(n) = O(n^log_b(a) - ε) → T(n) = Θ(n^log_b(a))
If f(n) = Θ(n^log_b(a))     → T(n) = Θ(n^log_b(a) log n)
If f(n) = Ω(n^log_b(a) + ε) → T(n) = Θ(f(n))

MODULE 1 – ARRAYS & STRINGS

1. Two Sum

// C++
vector<int> twoSum(vector<int>& nums, int target) {
    unordered_map<int, int> mp;
    for (int i = 0; i < nums.size(); i++) {
        int comp = target - nums[i];
        if (mp.count(comp)) return {mp[comp], i};
        mp[nums[i]] = i;
    }
    return {};
}
# Python
def twoSum(nums, target):
    mp = {}
    for i, n in enumerate(nums):
        if target - n in mp:
            return [mp[target - n], i]
        mp[n] = i
    return []

2. Trapping Rain Water

// C++ - Two Pointers
int trap(vector<int>& height) {
    int n = height.size(), l = 0, r = n-1;
    int leftMax = 0, rightMax = 0, water = 0;
    while (l < r) {
        if (height[l] < height[r]) {
            leftMax = max(leftMax, height[l]);
            water += leftMax - height[l++];
        } else {
            rightMax = max(rightMax, height[r]);
            water += rightMax - height[r--];
        }
    }
    return water;
}
# Python
def trap(height):
    l, r = 0, len(height)-1
    leftMax = rightMax = water = 0
    while l < r:
        if height[l] < height[r]:
            leftMax = max(leftMax, height[l])
            water += leftMax - height[l]
            l += 1
        else:
            rightMax = max(rightMax, height[r])
            water += rightMax - height[r]
            r -= 1
    return water

3. Longest Substring Without Repeating

// C++
int lengthOfLongestSubstring(string s) {
    unordered_map<char, int> lastSeen;
    int maxLen = 0, start = 0;
    for (int i = 0; i < s.size(); i++) {
        if (lastSeen.count(s[i]) && lastSeen[s[i]] >= start)
            start = lastSeen[s[i]] + 1;
        lastSeen[s[i]] = i;
        maxLen = max(maxLen, i - start + 1);
    }
    return maxLen;
}
# Python
def lengthOfLongestSubstring(s):
    lastSeen = {}
    maxLen = start = 0
    for i, c in enumerate(s):
        if c in lastSeen and lastSeen[c] >= start:
            start = lastSeen[c] + 1
        lastSeen[c] = i
        maxLen = max(maxLen, i - start + 1)
    return maxLen

4. Merge Intervals

// C++
vector<vector<int>> merge(vector<vector<int>>& intervals) {
    if (intervals.empty()) return {};
    sort(intervals.begin(), intervals.end());
    vector<vector<int>> res = {intervals[0]};
    for (auto& curr : intervals) {
        if (res.back()[1] >= curr[0])
            res.back()[1] = max(res.back()[1], curr[1]);
        else
            res.push_back(curr);
    }
    return res;
}
# Python
def merge(intervals):
    if not intervals: return []
    intervals.sort()
    res = [intervals[0]]
    for curr in intervals[1:]:
        if res[-1][1] >= curr[0]:
            res[-1][1] = max(res[-1][1], curr[1])
        else:
            res.append(curr)
    return res

MODULE 2 – LINKED LISTS

1. Reverse Linked List

// C++
ListNode* reverseList(ListNode* head) {
    ListNode *prev = nullptr, *curr = head;
    while (curr) {
        ListNode* next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
}
# Python
def reverseList(head):
    prev = None
    curr = head
    while curr:
        next_node = curr.next
        curr.next = prev
        prev = curr
        curr = next_node
    return prev

2. Detect Cycle (Floyd’s)

// C++
bool hasCycle(ListNode *head) {
    ListNode *slow = head, *fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) return true;
    }
    return false;
}
# Python
def hasCycle(head):
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast: return True
    return False

3. Merge Two Sorted Lists

// C++
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    ListNode dummy(0), *tail = &dummy;
    while (l1 && l2) {
        if (l1->val < l2->val) { tail->next = l1; l1 = l1->next; }
        else { tail->next = l2; l2 = l2->next; }
        tail = tail->next;
    }
    tail->next = l1 ? l1 : l2;
    return dummy.next;
}
# Python
def mergeTwoLists(l1, l2):
    dummy = ListNode(0)
    tail = dummy
    while l1 and l2:
        if l1.val < l2.val:
            tail.next = l1
            l1 = l1.next
        else:
            tail.next = l2
            l2 = l2.next
        tail = tail.next
    tail.next = l1 if l1 else l2
    return dummy.next

MODULE 3 – STACKS & QUEUES

1. Valid Parentheses

// C++
bool isValid(string s) {
    stack<char> st;
    for (char c : s) {
        if (c == '(' || c == '{' || c == '[') st.push(c);
        else {
            if (st.empty()) return false;
            char top = st.top(); st.pop();
            if ((c == ')' && top != '(') ||
                (c == '}' && top != '{') ||
                (c == ']' && top != '[')) return false;
        }
    }
    return st.empty();
}
# Python
def isValid(s):
    stack = []
    pairs = {')':'(', '}':'{', ']':'['}
    for c in s:
        if c in pairs:
            if not stack or stack.pop() != pairs[c]:
                return False
        else:
            stack.append(c)
    return not stack

2. Next Greater Element (Monotonic Stack)

// C++
vector<int> nextGreaterElement(vector<int>& nums) {
    int n = nums.size();
    vector<int> res(n, -1);
    stack<int> st;
    for (int i = 0; i < n; i++) {
        while (!st.empty() && nums[st.top()] < nums[i]) {
            res[st.top()] = nums[i];
            st.pop();
        }
        st.push(i);
    }
    return res;
}
# Python
def nextGreaterElement(nums):
    n = len(nums)
    res = [-1] * n
    stack = []
    for i in range(n):
        while stack and nums[stack[-1]] < nums[i]:
            res[stack.pop()] = nums[i]
        stack.append(i)
    return res

MODULE 4 – TREES

1. Inorder Traversal (Iterative)

// C++
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> st;
    TreeNode* curr = root;
    while (curr || !st.empty()) {
        while (curr) {
            st.push(curr);
            curr = curr->left;
        }
        curr = st.top(); st.pop();
        res.push_back(curr->val);
        curr = curr->right;
    }
    return res;
}
# Python
def inorderTraversal(root):
    res, stack = [], []
    curr = root
    while curr or stack:
        while curr:
            stack.append(curr)
            curr = curr.left
        curr = stack.pop()
        res.append(curr.val)
        curr = curr.right
    return res

2. Binary Tree Level Order

// C++
vector<vector<int>> levelOrder(TreeNode* root) {
    if (!root) return {};
    vector<vector<int>> res;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty()) {
        int size = q.size();
        vector<int> level;
        for (int i = 0; i < size; i++) {
            TreeNode* node = q.front(); q.pop();
            level.push_back(node->val);
            if (node->left) q.push(node->left);
            if (node->right) q.push(node->right);
        }
        res.push_back(level);
    }
    return res;
}
# Python
def levelOrder(root):
    if not root: return []
    res, q = [], [root]
    while q:
        level = []
        for _ in range(len(q)):
            node = q.pop(0)
            level.append(node.val)
            if node.left: q.append(node.left)
            if node.right: q.append(node.right)
        res.append(level)
    return res

3. Lowest Common Ancestor (BST)

// C++
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if (!root || !p || !q) return nullptr;
    if (root->val > max(p->val, q->val)) return lowestCommonAncestor(root->left, p, q);
    if (root->val < min(p->val, q->val)) return lowestCommonAncestor(root->right, p, q);
    return root;
}
# Python
def lowestCommonAncestor(root, p, q):
    if not root: return None
    if root.val > max(p.val, q.val):
        return lowestCommonAncestor(root.left, p, q)
    if root.val < min(p.val, q.val):
        return lowestCommonAncestor(root.right, p, q)
    return root

MODULE 5 – HEAPS

1. Kth Largest Element

// C++ - Min Heap
int findKthLargest(vector<int>& nums, int k) {
    priority_queue<int, vector<int>, greater<int>> pq;
    for (int num : nums) {
        pq.push(num);
        if (pq.size() > k) pq.pop();
    }
    return pq.top();
}
# Python
import heapq
def findKthLargest(nums, k):
    return heapq.nlargest(k, nums)[-1]

2. Merge K Sorted Lists

// C++ - Min Heap
ListNode* mergeKLists(vector<ListNode*>& lists) {
    auto comp = [](ListNode* a, ListNode* b) { return a->val > b->val; };
    priority_queue<ListNode*, vector<ListNode*>, decltype(comp)> pq(comp);
    for (auto l : lists) if (l) pq.push(l);
    ListNode dummy(0), *tail = &dummy;
    while (!pq.empty()) {
        ListNode* node = pq.top(); pq.pop();
        tail->next = node;
        tail = tail->next;
        if (node->next) pq.push(node->next);
    }
    return dummy.next;
}
# Python
import heapq
def mergeKLists(lists):
    heap = []
    for i, l in enumerate(lists):
        if l: heapq.heappush(heap, (l.val, i, l))
    dummy = ListNode(0)
    tail = dummy
    while heap:
        val, i, node = heapq.heappop(heap)
        tail.next = node
        tail = tail.next
        if node.next:
            heapq.heappush(heap, (node.next.val, i, node.next))
    return dummy.next

MODULE 6 – HASHING

1. LRU Cache

// C++
class LRUCache {
    int cap;
    list<pair<int,int>> dll;
    unordered_map<int, list<pair<int,int>>::iterator> mp;
public:
    LRUCache(int capacity) : cap(capacity) {}
    int get(int key) {
        if (mp.find(key) == mp.end()) return -1;
        dll.splice(dll.begin(), dll, mp[key]);
        mp[key] = dll.begin();
        return dll.begin()->second;
    }
    void put(int key, int value) {
        if (get(key) != -1) { dll.begin()->second = value; return; }
        if (dll.size() == cap) {
            int del = dll.back().first;
            dll.pop_back();
            mp.erase(del);
        }
        dll.push_front({key, value});
        mp[key] = dll.begin();
    }
};
# Python
class ListNode:
    def __init__(self, key=0, val=0):
        self.key = key
        self.val = val
        self.prev = self.next = None

class LRUCache:
    def __init__(self, capacity):
        self.cap = capacity
        self.cache = {}
        self.left = self.right = ListNode()
        self.left.next = self.right
        self.right.prev = self.left

    def _remove(self, node):
        node.prev.next = node.next
        node.next.prev = node.prev

    def _add(self, node):
        prev = self.right.prev
        prev.next = node
        node.prev = prev
        node.next = self.right
        self.right.prev = node

    def get(self, key):
        if key in self.cache:
            self._remove(self.cache[key])
            self._add(self.cache[key])
            return self.cache[key].val
        return -1

    def put(self, key, value):
        if key in self.cache:
            self._remove(self.cache[key])
        node = ListNode(key, value)
        self.cache[key] = node
        self._add(node)
        if len(self.cache) > self.cap:
            lru = self.left.next
            self._remove(lru)
            del self.cache[lru.key]

MODULE 7 – GRAPHS

1. BFS (Shortest Path)

// C++
vector<int> shortestPath(vector<vector<int>>& adj, int src) {
    int n = adj.size();
    vector<int> dist(n, -1);
    queue<int> q;
    q.push(src); dist[src] = 0;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int v : adj[u]) {
            if (dist[v] == -1) {
                dist[v] = dist[u] + 1;
                q.push(v);
            }
        }
    }
    return dist;
}
# Python
from collections import deque
def shortestPath(adj, src):
    n = len(adj)
    dist = [-1] * n
    q = deque([src])
    dist[src] = 0
    while q:
        u = q.popleft()
        for v in adj[u]:
            if dist[v] == -1:
                dist[v] = dist[u] + 1
                q.append(v)
    return dist

2. Dijkstra

// C++
vector<int> dijkstra(vector<vector<pair<int,int>>>& graph, int src) {
    int n = graph.size();
    vector<int> dist(n, INT_MAX);
    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;
    dist[src] = 0; pq.push({0, src});
    while (!pq.empty()) {
        auto [d, u] = pq.top(); pq.pop();
        if (d > dist[u]) continue;
        for (auto [v, w] : graph[u]) {
            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                pq.push({dist[v], v});
            }
        }
    }
    return dist;
}
# Python
import heapq
def dijkstra(graph, src):
    n = len(graph)
    dist = [float('inf')] * n
    dist[src] = 0
    pq = [(0, src)]
    while pq:
        d, u = heapq.heappop(pq)
        if d > dist[u]: continue
        for v, w in graph[u]:
            if dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                heapq.heappush(pq, (dist[v], v))
    return dist

MODULE 8 – DYNAMIC PROGRAMMING

1. 0/1 Knapsack

// C++
int knapsack(vector<int>& wt, vector<int>& val, int W) {
    int n = wt.size();
    vector<vector<int>> dp(n+1, vector<int>(W+1, 0));
    for (int i = 1; i <= n; i++) {
        for (int w = 1; w <= W; w++) {
            if (wt[i-1] <= w)
                dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w]);
            else
                dp[i][w] = dp[i-1][w];
        }
    }
    return dp[n][W];
}
# Python
def knapsack(wt, val, W):
    n = len(val)
    dp = [[0]*(W+1) for _ in range(n+1)]
    for i in range(1, n+1):
        for w in range(1, W+1):
            if wt[i-1] <= w:
                dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w])
            else:
                dp[i][w] = dp[i-1][w]
    return dp[n][W]

2. Longest Common Subsequence

// C++
int longestCommonSubsequence(string text1, string text2) {
    int n = text1.size(), m = text2.size();
    vector<vector<int>> dp(n+1, vector<int>(m+1, 0));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (text1[i-1] == text2[j-1])
                dp[i][j] = dp[i-1][j-1] + 1;
            else
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
        }
    }
    return dp[n][m];
}
# Python
def longestCommonSubsequence(text1, text2):
    n, m = len(text1), len(text2)
    dp = [[0]*(m+1) for _ in range(n+1)]
    for i in range(1, n+1):
        for j in range(1, m+1):
            if text1[i-1] == text2[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
            else:
                dp[i][j] = max(dp[i-1][j], dp[i][j-1])
    return dp[n][m]

MODULE 9 – ADVANCED

1. Union-Find (DSU)

// C++
class DSU {
    vector<int> parent, rank;
public:
    DSU(int n) {
        parent.resize(n); rank.resize(n, 0);
        for (int i = 0; i < n; i++) parent[i] = i;
    }
    int find(int x) {
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }
    void union_sets(int x, int y) {
        int px = find(x), py = find(y);
        if (px == py) return;
        if (rank[px] < rank[py]) swap(px, py);
        parent[py] = px;
        if (rank[px] == rank[py]) rank[px]++;
    }
};
# Python
class DSU:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n
    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    def union(self, x, y):
        px, py = self.find(x), self.find(y)
        if px == py: return
        if self.rank[px] < self.rank[py]:
            px, py = py, px
        self.parent[py] = px
        if self.rank[px] == self.rank[py]:
            self.rank[px] += 1

All code is ready to copy-paste into LeetCode/IDE.
Want PDF version, Notion database, or video walkthroughs? Let me know!

Last updated: Nov 10, 2025

DATA STRUCTURES & ALGORITHMS – FULL COURSE NOTES

Below is a complete, self-contained DSA course note set with every code example in both C++ and Python, organized by modules. All code is tested, concise, and production-ready for interviews (LeetCode-style).

DATA STRUCTURES & ALGORITHMS – FULL COURSE NOTES With C++ & Python Code Examples

DATA STRUCTURES & ALGORITHMS – FULL COURSE NOTES With C++ & Python Code Examples

Below is a complete, self-contained DSA course note set with every code example in both C++ and Python, organized by modules.
All code is tested, concise, and production-ready for interviews (LeetCode-style).


DATA STRUCTURES & ALGORITHMS – FULL COURSE NOTES

With C++ & Python Code Examples


MODULE 0 – COMPLEXITY ANALYSIS

Notation Meaning
O(f(n)) Upper bound
Ω(f(n)) Lower bound
Θ(f(n)) Tight bound

Master Theorem

For T(n) = aT(n/b) + f(n):

If f(n) = O(n^log_b(a) - ε) → T(n) = Θ(n^log_b(a))
If f(n) = Θ(n^log_b(a))     → T(n) = Θ(n^log_b(a) log n)
If f(n) = Ω(n^log_b(a) + ε) → T(n) = Θ(f(n))

MODULE 1 – ARRAYS & STRINGS

1. Two Sum

// C++
vector<int> twoSum(vector<int>& nums, int target) {
    unordered_map<int, int> mp;
    for (int i = 0; i < nums.size(); i++) {
        int comp = target - nums[i];
        if (mp.count(comp)) return {mp[comp], i};
        mp[nums[i]] = i;
    }
    return {};
}
# Python
def twoSum(nums, target):
    mp = {}
    for i, n in enumerate(nums):
        if target - n in mp:
            return [mp[target - n], i]
        mp[n] = i
    return []

2. Trapping Rain Water

// C++ - Two Pointers
int trap(vector<int>& height) {
    int n = height.size(), l = 0, r = n-1;
    int leftMax = 0, rightMax = 0, water = 0;
    while (l < r) {
        if (height[l] < height[r]) {
            leftMax = max(leftMax, height[l]);
            water += leftMax - height[l++];
        } else {
            rightMax = max(rightMax, height[r]);
            water += rightMax - height[r--];
        }
    }
    return water;
}
# Python
def trap(height):
    l, r = 0, len(height)-1
    leftMax = rightMax = water = 0
    while l < r:
        if height[l] < height[r]:
            leftMax = max(leftMax, height[l])
            water += leftMax - height[l]
            l += 1
        else:
            rightMax = max(rightMax, height[r])
            water += rightMax - height[r]
            r -= 1
    return water

3. Longest Substring Without Repeating

// C++
int lengthOfLongestSubstring(string s) {
    unordered_map<char, int> lastSeen;
    int maxLen = 0, start = 0;
    for (int i = 0; i < s.size(); i++) {
        if (lastSeen.count(s[i]) && lastSeen[s[i]] >= start)
            start = lastSeen[s[i]] + 1;
        lastSeen[s[i]] = i;
        maxLen = max(maxLen, i - start + 1);
    }
    return maxLen;
}
# Python
def lengthOfLongestSubstring(s):
    lastSeen = {}
    maxLen = start = 0
    for i, c in enumerate(s):
        if c in lastSeen and lastSeen[c] >= start:
            start = lastSeen[c] + 1
        lastSeen[c] = i
        maxLen = max(maxLen, i - start + 1)
    return maxLen

4. Merge Intervals

// C++
vector<vector<int>> merge(vector<vector<int>>& intervals) {
    if (intervals.empty()) return {};
    sort(intervals.begin(), intervals.end());
    vector<vector<int>> res = {intervals[0]};
    for (auto& curr : intervals) {
        if (res.back()[1] >= curr[0])
            res.back()[1] = max(res.back()[1], curr[1]);
        else
            res.push_back(curr);
    }
    return res;
}
# Python
def merge(intervals):
    if not intervals: return []
    intervals.sort()
    res = [intervals[0]]
    for curr in intervals[1:]:
        if res[-1][1] >= curr[0]:
            res[-1][1] = max(res[-1][1], curr[1])
        else:
            res.append(curr)
    return res

MODULE 2 – LINKED LISTS

1. Reverse Linked List

// C++
ListNode* reverseList(ListNode* head) {
    ListNode *prev = nullptr, *curr = head;
    while (curr) {
        ListNode* next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
    return prev;
}
# Python
def reverseList(head):
    prev = None
    curr = head
    while curr:
        next_node = curr.next
        curr.next = prev
        prev = curr
        curr = next_node
    return prev

2. Detect Cycle (Floyd’s)

// C++
bool hasCycle(ListNode *head) {
    ListNode *slow = head, *fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) return true;
    }
    return false;
}
# Python
def hasCycle(head):
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast: return True
    return False

3. Merge Two Sorted Lists

// C++
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    ListNode dummy(0), *tail = &dummy;
    while (l1 && l2) {
        if (l1->val < l2->val) { tail->next = l1; l1 = l1->next; }
        else { tail->next = l2; l2 = l2->next; }
        tail = tail->next;
    }
    tail->next = l1 ? l1 : l2;
    return dummy.next;
}
# Python
def mergeTwoLists(l1, l2):
    dummy = ListNode(0)
    tail = dummy
    while l1 and l2:
        if l1.val < l2.val:
            tail.next = l1
            l1 = l1.next
        else:
            tail.next = l2
            l2 = l2.next
        tail = tail.next
    tail.next = l1 if l1 else l2
    return dummy.next

MODULE 3 – STACKS & QUEUES

1. Valid Parentheses

// C++
bool isValid(string s) {
    stack<char> st;
    for (char c : s) {
        if (c == '(' || c == '{' || c == '[') st.push(c);
        else {
            if (st.empty()) return false;
            char top = st.top(); st.pop();
            if ((c == ')' && top != '(') ||
                (c == '}' && top != '{') ||
                (c == ']' && top != '[')) return false;
        }
    }
    return st.empty();
}
# Python
def isValid(s):
    stack = []
    pairs = {')':'(', '}':'{', ']':'['}
    for c in s:
        if c in pairs:
            if not stack or stack.pop() != pairs[c]:
                return False
        else:
            stack.append(c)
    return not stack

2. Next Greater Element (Monotonic Stack)

// C++
vector<int> nextGreaterElement(vector<int>& nums) {
    int n = nums.size();
    vector<int> res(n, -1);
    stack<int> st;
    for (int i = 0; i < n; i++) {
        while (!st.empty() && nums[st.top()] < nums[i]) {
            res[st.top()] = nums[i];
            st.pop();
        }
        st.push(i);
    }
    return res;
}
# Python
def nextGreaterElement(nums):
    n = len(nums)
    res = [-1] * n
    stack = []
    for i in range(n):
        while stack and nums[stack[-1]] < nums[i]:
            res[stack.pop()] = nums[i]
        stack.append(i)
    return res

MODULE 4 – TREES

1. Inorder Traversal (Iterative)

// C++
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> res;
    stack<TreeNode*> st;
    TreeNode* curr = root;
    while (curr || !st.empty()) {
        while (curr) {
            st.push(curr);
            curr = curr->left;
        }
        curr = st.top(); st.pop();
        res.push_back(curr->val);
        curr = curr->right;
    }
    return res;
}
# Python
def inorderTraversal(root):
    res, stack = [], []
    curr = root
    while curr or stack:
        while curr:
            stack.append(curr)
            curr = curr.left
        curr = stack.pop()
        res.append(curr.val)
        curr = curr.right
    return res

2. Binary Tree Level Order

// C++
vector<vector<int>> levelOrder(TreeNode* root) {
    if (!root) return {};
    vector<vector<int>> res;
    queue<TreeNode*> q;
    q.push(root);
    while (!q.empty()) {
        int size = q.size();
        vector<int> level;
        for (int i = 0; i < size; i++) {
            TreeNode* node = q.front(); q.pop();
            level.push_back(node->val);
            if (node->left) q.push(node->left);
            if (node->right) q.push(node->right);
        }
        res.push_back(level);
    }
    return res;
}
# Python
def levelOrder(root):
    if not root: return []
    res, q = [], [root]
    while q:
        level = []
        for _ in range(len(q)):
            node = q.pop(0)
            level.append(node.val)
            if node.left: q.append(node.left)
            if node.right: q.append(node.right)
        res.append(level)
    return res

3. Lowest Common Ancestor (BST)

// C++
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    if (!root || !p || !q) return nullptr;
    if (root->val > max(p->val, q->val)) return lowestCommonAncestor(root->left, p, q);
    if (root->val < min(p->val, q->val)) return lowestCommonAncestor(root->right, p, q);
    return root;
}
# Python
def lowestCommonAncestor(root, p, q):
    if not root: return None
    if root.val > max(p.val, q.val):
        return lowestCommonAncestor(root.left, p, q)
    if root.val < min(p.val, q.val):
        return lowestCommonAncestor(root.right, p, q)
    return root

MODULE 5 – HEAPS

1. Kth Largest Element

// C++ - Min Heap
int findKthLargest(vector<int>& nums, int k) {
    priority_queue<int, vector<int>, greater<int>> pq;
    for (int num : nums) {
        pq.push(num);
        if (pq.size() > k) pq.pop();
    }
    return pq.top();
}
# Python
import heapq
def findKthLargest(nums, k):
    return heapq.nlargest(k, nums)[-1]

2. Merge K Sorted Lists

// C++ - Min Heap
ListNode* mergeKLists(vector<ListNode*>& lists) {
    auto comp = [](ListNode* a, ListNode* b) { return a->val > b->val; };
    priority_queue<ListNode*, vector<ListNode*>, decltype(comp)> pq(comp);
    for (auto l : lists) if (l) pq.push(l);
    ListNode dummy(0), *tail = &dummy;
    while (!pq.empty()) {
        ListNode* node = pq.top(); pq.pop();
        tail->next = node;
        tail = tail->next;
        if (node->next) pq.push(node->next);
    }
    return dummy.next;
}
# Python
import heapq
def mergeKLists(lists):
    heap = []
    for i, l in enumerate(lists):
        if l: heapq.heappush(heap, (l.val, i, l))
    dummy = ListNode(0)
    tail = dummy
    while heap:
        val, i, node = heapq.heappop(heap)
        tail.next = node
        tail = tail.next
        if node.next:
            heapq.heappush(heap, (node.next.val, i, node.next))
    return dummy.next

MODULE 6 – HASHING

1. LRU Cache

// C++
class LRUCache {
    int cap;
    list<pair<int,int>> dll;
    unordered_map<int, list<pair<int,int>>::iterator> mp;
public:
    LRUCache(int capacity) : cap(capacity) {}
    int get(int key) {
        if (mp.find(key) == mp.end()) return -1;
        dll.splice(dll.begin(), dll, mp[key]);
        mp[key] = dll.begin();
        return dll.begin()->second;
    }
    void put(int key, int value) {
        if (get(key) != -1) { dll.begin()->second = value; return; }
        if (dll.size() == cap) {
            int del = dll.back().first;
            dll.pop_back();
            mp.erase(del);
        }
        dll.push_front({key, value});
        mp[key] = dll.begin();
    }
};
# Python
class ListNode:
    def __init__(self, key=0, val=0):
        self.key = key
        self.val = val
        self.prev = self.next = None

class LRUCache:
    def __init__(self, capacity):
        self.cap = capacity
        self.cache = {}
        self.left = self.right = ListNode()
        self.left.next = self.right
        self.right.prev = self.left

    def _remove(self, node):
        node.prev.next = node.next
        node.next.prev = node.prev

    def _add(self, node):
        prev = self.right.prev
        prev.next = node
        node.prev = prev
        node.next = self.right
        self.right.prev = node

    def get(self, key):
        if key in self.cache:
            self._remove(self.cache[key])
            self._add(self.cache[key])
            return self.cache[key].val
        return -1

    def put(self, key, value):
        if key in self.cache:
            self._remove(self.cache[key])
        node = ListNode(key, value)
        self.cache[key] = node
        self._add(node)
        if len(self.cache) > self.cap:
            lru = self.left.next
            self._remove(lru)
            del self.cache[lru.key]

MODULE 7 – GRAPHS

1. BFS (Shortest Path)

// C++
vector<int> shortestPath(vector<vector<int>>& adj, int src) {
    int n = adj.size();
    vector<int> dist(n, -1);
    queue<int> q;
    q.push(src); dist[src] = 0;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int v : adj[u]) {
            if (dist[v] == -1) {
                dist[v] = dist[u] + 1;
                q.push(v);
            }
        }
    }
    return dist;
}
# Python
from collections import deque
def shortestPath(adj, src):
    n = len(adj)
    dist = [-1] * n
    q = deque([src])
    dist[src] = 0
    while q:
        u = q.popleft()
        for v in adj[u]:
            if dist[v] == -1:
                dist[v] = dist[u] + 1
                q.append(v)
    return dist

2. Dijkstra

// C++
vector<int> dijkstra(vector<vector<pair<int,int>>>& graph, int src) {
    int n = graph.size();
    vector<int> dist(n, INT_MAX);
    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;
    dist[src] = 0; pq.push({0, src});
    while (!pq.empty()) {
        auto [d, u] = pq.top(); pq.pop();
        if (d > dist[u]) continue;
        for (auto [v, w] : graph[u]) {
            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                pq.push({dist[v], v});
            }
        }
    }
    return dist;
}
# Python
import heapq
def dijkstra(graph, src):
    n = len(graph)
    dist = [float('inf')] * n
    dist[src] = 0
    pq = [(0, src)]
    while pq:
        d, u = heapq.heappop(pq)
        if d > dist[u]: continue
        for v, w in graph[u]:
            if dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                heapq.heappush(pq, (dist[v], v))
    return dist

MODULE 8 – DYNAMIC PROGRAMMING

1. 0/1 Knapsack

// C++
int knapsack(vector<int>& wt, vector<int>& val, int W) {
    int n = wt.size();
    vector<vector<int>> dp(n+1, vector<int>(W+1, 0));
    for (int i = 1; i <= n; i++) {
        for (int w = 1; w <= W; w++) {
            if (wt[i-1] <= w)
                dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w]);
            else
                dp[i][w] = dp[i-1][w];
        }
    }
    return dp[n][W];
}
# Python
def knapsack(wt, val, W):
    n = len(val)
    dp = [[0]*(W+1) for _ in range(n+1)]
    for i in range(1, n+1):
        for w in range(1, W+1):
            if wt[i-1] <= w:
                dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w])
            else:
                dp[i][w] = dp[i-1][w]
    return dp[n][W]

2. Longest Common Subsequence

// C++
int longestCommonSubsequence(string text1, string text2) {
    int n = text1.size(), m = text2.size();
    vector<vector<int>> dp(n+1, vector<int>(m+1, 0));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (text1[i-1] == text2[j-1])
                dp[i][j] = dp[i-1][j-1] + 1;
            else
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
        }
    }
    return dp[n][m];
}
# Python
def longestCommonSubsequence(text1, text2):
    n, m = len(text1), len(text2)
    dp = [[0]*(m+1) for _ in range(n+1)]
    for i in range(1, n+1):
        for j in range(1, m+1):
            if text1[i-1] == text2[j-1]:
                dp[i][j] = dp[i-1][j-1] + 1
            else:
                dp[i][j] = max(dp[i-1][j], dp[i][j-1])
    return dp[n][m]

MODULE 9 – ADVANCED

1. Union-Find (DSU)

// C++
class DSU {
    vector<int> parent, rank;
public:
    DSU(int n) {
        parent.resize(n); rank.resize(n, 0);
        for (int i = 0; i < n; i++) parent[i] = i;
    }
    int find(int x) {
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }
    void union_sets(int x, int y) {
        int px = find(x), py = find(y);
        if (px == py) return;
        if (rank[px] < rank[py]) swap(px, py);
        parent[py] = px;
        if (rank[px] == rank[py]) rank[px]++;
    }
};
# Python
class DSU:
    def __init__(self, n):
        self.parent = list(range(n))
        self.rank = [0] * n
    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    def union(self, x, y):
        px, py = self.find(x), self.find(y)
        if px == py: return
        if self.rank[px] < self.rank[py]:
            px, py = py, px
        self.parent[py] = px
        if self.rank[px] == self.rank[py]:
            self.rank[px] += 1

All code is ready to copy-paste into LeetCode/IDE.
Want PDF version, Notion database, or video walkthroughs? Let me know!

Last updated: Nov 10, 2025