Blog

Cramming LeetCode in 48 Hours: A Realistic Study Plan

If your interview is two days away, you cannot learn 50 separate algorithms, but you can learn about eight patterns and apply them to roughly 20 to 25 well-chosen problems. Interview questions are mostly variations on a small set of ideas: hash maps, two pointers and sliding windows, stacks, binary search, tree and graph traversal, heaps, and basic dynamic programming. This plan spends 48 hours on those ideas, in the order that pays off fastest, and tells you what to skip.

It is a damage-control plan, not a good way to prepare. If you have more than a week, spread the same material over more days; retention is far better.

What 48 hours can and cannot do

Be honest about the goal. You are not going to master anything in two days. You can get to the point where, given a new easy or medium problem, you recognize which pattern it belongs to, write a clean first solution, and explain your reasoning out loud. That is also what most interviewers are looking for.

So the unit of study is the pattern, not the problem. For each pattern you do three things: read one short template, solve two problems with it, and then explain the solution aloud without looking. Fifty problems solved by reading solutions teach you much less than twenty problems you wrote yourself.

The schedule

Plan for about 8 to 9 productive hours per day, with sleep. Skipping sleep is the most common mistake in cramming: memory consolidation happens overnight, and a tired brain also makes careless bugs in the interview.

Block Day 1 Day 2
Morning (3 h) Hash maps, two pointers, sliding window Graphs: BFS, DFS, cycle detection
Afternoon (3 h) Stacks, binary search Heaps, basic dynamic programming
Evening (2 to 3 h) Linked lists, trees (DFS and BFS) Two timed mock problems, out loud; review your notes

Take a 10 to 15 minute break every 90 minutes and stop studying new material a few hours before sleep on day 2. The last evening is for review, not for new topics.

The routine for every problem

  1. Read the problem and spend 5 minutes writing down the brute force solution and its complexity. If you cannot, that is the thing to fix.
  2. Ask which pattern fits, and why. “We need to look up a complement fast” points to a hash map; “contiguous range with a condition” points to a sliding window.
  3. Code it yourself. If you are stuck after 20 minutes, read the hint or the solution, close it, and write it again from memory.
  4. Run a small example by hand, including an empty input and a single element.
  5. Write one line in your notes: pattern, key trick, complexity.

Day 1: hash maps, windows, stacks, binary search, trees

Hash maps: Two Sum

Whenever a brute force solution does a nested loop to find a matching value, ask whether a dictionary can answer “have I seen the value I need?” in constant time. Two Sum is the standard example: for each number, check whether target - x was already seen.

def two_sum(nums, target):
    seen = {}
    for i, x in enumerate(nums):
        if target - x in seen:
            return [seen[target - x], i]
        seen[x] = i
    return []

This runs in O(n) time and O(n) space. two_sum([2, 7, 11, 15], 9) returns [0, 1]. Then try Ransom Note, Group Anagrams and Longest Consecutive Sequence.

Sliding window: longest substring without repeating characters

When the question is about the longest or shortest contiguous piece of an array or string that satisfies a condition, keep a window with a left edge that only moves forward. Each element enters and leaves the window once, so the whole thing is O(n).

def longest_unique(s):
    last = {}
    start = best = 0
    for i, ch in enumerate(s):
        if ch in last and last[ch] >= start:
            start = last[ch] + 1
        last[ch] = i
        best = max(best, i - start + 1)
    return best

The detail people get wrong is the last[ch] >= start check: a character seen before the current window must not move the left edge backwards. On "abba" the answer is 2; a version without that check returns 3. The lesson Sliding Window Technique covers the pattern step by step, and the blog has a longer article on sliding window techniques.

Two pointers is the sibling pattern for sorted input or in-place edits (palindromes, merging sorted arrays, container with most water). Do one or two of those next.

Stacks: valid parentheses

A stack fits any problem where the most recent unmatched thing must be resolved first: brackets, nested expressions, “next greater element”.

def is_valid(s):
    pairs = {")": "(", "]": "[", "}": "{"}
    stack = []
    for ch in s:
        if ch in pairs:
            if not stack or stack.pop() != pairs[ch]:
                return False
        else:
            stack.append(ch)
    return not stack

It returns True for "([]){}" and False for "(]" and for "((". The last case is the one beginners forget: an unclosed bracket leaves the stack non-empty, so the final not stack matters. There is a guided version in the Valid Parentheses lesson.

Binary search

Use it when the data is sorted, or when you can ask a yes/no question that flips from false to true at some point (the smallest speed that finishes in time, for example). Write it the same way every time so you do not have to think about off-by-one errors in the interview.

def binary_search(a, target):
    lo, hi = 0, len(a) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if a[mid] == target:
            return mid
        if a[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1

Searching [1, 3, 5, 7, 9] for 7 returns index 3, and for 4 returns -1. Then practice variants: first occurrence, insert position, search on the answer.

Linked lists and trees

For linked lists, learn three things: reverse a list iteratively, use a dummy head node when building or merging lists, and use slow and fast pointers to find the middle or detect a cycle. Try Reverse Linked List first.

For trees, almost everything is either recursion that returns something from the left and right subtrees (depth, validate a BST with bounds, diameter) or a level-by-level traversal with a queue:

from collections import deque

class Node:
    def __init__(self, val, left=None, right=None):
        self.val, self.left, self.right = val, left, right

def level_order(root):
    if not root:
        return []
    out, q = [], deque([root])
    while q:
        level = []
        for _ in range(len(q)):
            n = q.popleft()
            level.append(n.val)
            if n.left: q.append(n.left)
            if n.right: q.append(n.right)
        out.append(level)
    return out

On a tree with root 3, children 9 and 20, and 20’s children 15 and 7, this returns [[3], [9, 20], [15, 7]]. Practice inorder traversal and tree depth for the recursive style.

Day 2: graphs, heaps, dynamic programming

Graphs: BFS, DFS and cycle detection

Most graph questions in interviews are one of: count or find connected pieces (DFS or BFS), shortest path in an unweighted graph (BFS), or ordering and cycles in a directed graph (topological sort or DFS with three states). Course Schedule is the classic cycle question:

def can_finish(n, prereqs):
    graph = [[] for _ in range(n)]
    for course, pre in prereqs:
        graph[pre].append(course)
    state = [0] * n  # 0 new, 1 on current path, 2 done
    def has_cycle(u):
        if state[u] == 1: return True
        if state[u] == 2: return False
        state[u] = 1
        if any(has_cycle(v) for v in graph[u]): return True
        state[u] = 2
        return False
    return not any(has_cycle(i) for i in range(n))

can_finish(2, [[1, 0]]) is True, and can_finish(2, [[1, 0], [0, 1]]) is False. The three states matter: “on the current path” means a cycle if you reach it again, while “done” means you can skip it. Marking nodes only as visited, with no distinction, either misses cycles or reports false ones. For recursion depth, note that Python’s default limit is about 1,000 frames, so mention an iterative version if the interviewer gives you a very deep graph.

Heaps

Reach for a heap when you repeatedly need the smallest or largest item, or the top k of something. Keeping a min-heap of size k gives the k-th largest element in O(n log k):

import heapq

def k_largest(nums, k):
    heap = []
    for x in nums:
        heapq.heappush(heap, x)
        if len(heap) > k:
            heapq.heappop(heap)
    return heap[0]

For [3, 2, 1, 5, 6, 4] and k = 2 it returns 5. The same idea powers Merge K Sorted Lists; practice it on that problem.

Dynamic programming, the small version

Do not try to learn all of dynamic programming in a few hours. Learn the routine: define what dp[i] means in one sentence, write the recurrence, set the base case, and decide the order of filling. Then do Climbing Stairs, Coin Change and House Robber, and stop.

def coin_change(coins, amount):
    INF = amount + 1
    dp = [0] + [INF] * amount
    for a in range(1, amount + 1):
        for c in coins:
            if c <= a:
                dp[a] = min(dp[a], dp[a - c] + 1)
    return dp[amount] if dp[amount] != INF else -1

Here dp[a] is the fewest coins that make amount a. coin_change([1, 2, 5], 11) returns 3 (5 + 5 + 1) and coin_change([2], 3) returns -1. Time is O(amount x number of coins).

One design question: LRU cache

If the company asks design-flavored questions, an LRU cache comes up often. In Python, OrderedDict gives O(1) get and put. Interviewers may ask you to build the hash map plus doubly linked list yourself, so know that this version is the shortcut and be ready to explain what it hides.

from collections import OrderedDict

class LRUCache:
    def __init__(self, capacity):
        self.cap, self.d = capacity, OrderedDict()
    def get(self, key):
        if key not in self.d: return -1
        self.d.move_to_end(key)
        return self.d[key]
    def put(self, key, value):
        self.d[key] = value
        self.d.move_to_end(key)
        if len(self.d) > self.cap:
            self.d.popitem(last=False)

With capacity 2, after putting keys 1 and 2, reading key 1, and putting key 3, the cache returns -1 for key 2 (evicted), 1 for key 1 and 3 for key 3.

The last evening

  • Do two timed problems of medium difficulty, 30 to 40 minutes each, speaking as you would in the interview: restate the problem, give the brute force, name the pattern, code, test with an example.
  • Reread your one-line notes from each problem. Do not start new topics.
  • Prepare the setup: editor or shared-doc environment, the language you will use, and a quiet place. Confirm the format with the recruiter if you can; many companies share it in advance.
  • Sleep.

Common mistakes when cramming

  • Reading solutions instead of writing them. Recognition feels like understanding but fails when you face a blank editor.
  • Starting with the hardest topics. Dynamic programming and advanced graphs have the lowest return per hour. Hash maps, two pointers and trees pay off more, so cover those first.
  • Skipping edge cases. Empty input, one element, duplicates and negative numbers cause most interview bugs.
  • Going silent. Interviewers grade your reasoning as well as the answer. If you are stuck, say what you have tried and what you are considering.
  • Memorizing code. Memorized code breaks as soon as the interviewer changes one condition. Memorize the pattern and rebuild the code.

After the interview, or if you have more time

Once this deadline passes, the cheaper path is consistency: a few problems a day for several weeks, repeating the ones you failed after a few days. If you want guided practice, AlgoCademy has step-by-step lessons grouped by the same patterns as above, with an AI tutor you can ask when stuck. Other options include solving curated lists on LeetCode or reading a book, and which one suits you depends on whether you prefer structured lessons or open problem banks. Our post on why daily practice can still leave you stuck on medium problems explains what to change if practice is not paying off.

A lesson in AlgoCademy: the step to write, a picture of what it does, the line written in the editor, and the check: Step 2 passed

Before you go

Start thinking like a software engineer.

Learn to code and solve interview problems, one small, checked step at a time.

Free, no card needed. Or look around first

By continuing you agree to the Terms of Service and Privacy Policy.