Two Sum, sliding window, BFS on a grid - the problems that show up in every interview, with the data structure visible at every step. Pause, rewind, edit the input, and ask 'why does this work?' until you actually know.
New to this section? Work through these in order - each builds on the previous.
The brute-force solution checks every pair in O(n²). The hash-map trick: as we scan left-to-right, for each nums[i] we look up its complement (target − nums[i]) in a map of values we've already seen. The map turns the inner loop's linear scan into an O(1) lookup, so the whole thing runs in a single O(n) pass.
Walk left-to-right with a stack. Every opener gets pushed; every closer pops and must match the top. If you ever pop the wrong opener - or pop from an empty stack - the string is invalid. After the loop, the stack must be empty for the string to be valid. The stack is the perfect data structure here because brackets nest like function calls.
The brute force is to try every (buy, sell) pair - O(n²). The trick is realizing you don't need to revisit history: for each day, the best sell-today profit is today's price minus the cheapest price seen so far. So track running min and running max-profit in one pass.
To reach step n, the LAST move you made was either a 1-step (from n-1) or a 2-step (from n-2). So the number of ways to reach n is the sum of the ways to reach n-1 and n-2. That's Fibonacci. Building the dp table bottom-up - dp[0]=1, dp[1]=1, then dp[i] = dp[i-1] + dp[i-2] - gives O(n) time, O(n) space; you can compress to two variables for O(1) space.
Three pointers do the whole job: prev (everything we've reversed so far), curr (the node we're about to flip), and nxt (saved so we don't lose the rest of the list). On each iteration: save nxt, flip curr.next to point at prev, then march all three pointers one step forward. At the end, prev is the new head.
Two pointers, one for each list. Each step: compare heads, take the smaller one, advance that pointer. When one list runs out, append the rest of the other. The two lists must be pre-sorted; if they aren't, you're doing merge-sort's merge step on unsorted data and you'll get garbage.
At every index, you have one decision: extend the running subarray, or start fresh from here. You restart when the running sum has gone negative - a negative prefix can only hurt anything you'd add after it. This dynamic-programming insight collapses the O(n³) brute force into O(n), and it's exactly the same shape as 'best time to buy/sell stock' written with a different variable.
A palindrome reads the same forwards and backwards. Walk one pointer from each end toward the middle; if every pair matches, the string is a palindrome. The wrinkle is the problem's filter - only alphanumeric characters count and case is ignored - so when either pointer lands on punctuation or whitespace, slide it past before comparing. The moment a pair fails, you can return false immediately.
Three reversals = one rotation. To right-rotate an array by k, first reverse the entire array - that swings every element across the midpoint but also reverses the two halves you actually want. Reverse the first k elements to un-swap that prefix, then reverse the remaining n − k to un-swap the suffix. The two locally-reversed halves cancel the global reversal exactly where you want them to. The whole thing runs in O(n) time with no extra space, beating the naive copy-into-a-buffer approach.
Water trapped over a column equals min(leftMax, rightMax) - height. The clean O(n) trick uses two pointers moving inward. Whichever side's running max is smaller is also the binding constraint for the column on that side: water at that column cannot exceed it, because the OTHER side's max is even taller. So advance the smaller side, settle that column's water as (sideMax - height), update the side's max, and keep going until the pointers meet. No stacks, no extra arrays.
Sorting is the trick. Once nums is sorted, fix one element nums[i] and the problem becomes 'find two values to its right that sum to -nums[i]' - a two-pointer sweep from both ends. If the current trio's sum is too small, advance l (left pointer) to pick up a bigger value; too big, retreat r. When you find a hit, record it, then skip duplicate neighbors on both sides so the same triplet isn't reported twice. Skipping duplicate anchors (nums[i] == nums[i-1]) keeps the result clean too. O(n²) total, beating the brute-force O(n³).
Every palindrome has a center - either a single character (odd length: 'racecar') or the gap between two characters (even length: 'abba'). For each possible center, expand outwards as long as the two sides keep matching. Track the longest palindrome you see. There are 2n - 1 possible centers and each expansion is O(n) in the worst case, giving O(n²) total - faster than brute-force enumeration and simpler than DP.
A variable-size sliding window. The right pointer always advances; the left pointer jumps forward whenever the incoming character would create a duplicate, shrinking the window until the offender is evicted. A hash set tracks what's in the window so the duplicate-check is O(1). Each character is visited at most twice (once by right, once by left) - total O(n).
Walk the matrix in spiral order: right across the top row, down the right column, left across the bottom, up the left side - then repeat on the contracting inner rectangle. Track four boundaries (top, bottom, left, right) and shrink the relevant one after each directional walk. The trick that catches interview candidates: after walking right and down, you must also check `top <= bottom` and `left <= right` before walking left and up - otherwise on a single-row or single-column residue you'll double-walk and duplicate elements.
A 90°-clockwise rotation is the same thing as transpose + horizontal flip. Transpose swaps element (i, j) with (j, i) - turning rows into columns. After that, reversing each row flips left↔right, which finishes the rotation. Both operations work in place, so the whole rotation runs in O(n²) time with O(1) extra space. You can also do it with four-way ring swaps; the transpose-then-flip framing is just easier to remember and easier to read.
Inorder = LEFT subtree, then NODE, then RIGHT subtree. The recursive version is three lines. The iterative version with an explicit stack is more interesting: you descend left as far as you can, pushing each node, then pop, visit, and try the right subtree. The stack lets you remember where to come back to. For BSTs, inorder produces values in sorted order - that's the property tests rely on.
Scan the grid row-by-row. Every time you hit unvisited land, you've found a new island - bump the count, then flood-fill the connected region so you don't double-count it. The flood-fill is just DFS (or BFS) over 4-directional neighbors, marking each cell as visited when you touch it. Each cell is processed at most once, so the total work is O(rows × cols).
Walk a row of houses; you can't rob two adjacent ones. At each house i, the best you can do is either *rob this one* (take nums[i] + best from houses 0..i-2) or *skip it* (carry forward the best from 0..i-1). Take whichever is larger. That's the recurrence dp[i] = max(dp[i-1], dp[i-2] + nums[i]). Build the dp table left-to-right and the last cell is the answer. Pedagogically: each step you literally see one of two paths win - taking-current vs. carrying-prior.
Build the answer bottom-up. dp[i] holds the minimum coins to reach amount i. Start with dp[0] = 0 (zero coins make zero). For every amount from 1 up to the target, try each coin c: if we can subtract c (i ≥ c), then one possible recipe is dp[i − c] + 1. Take the minimum across all coins. Any slot that never gets updated stays unreachable - return -1 at the end if dp[amount] is still ∞.
dp[i] = true iff the first i characters of s can be carved into dictionary words. dp[0] starts true (the empty prefix is trivially segmentable). For each new length i, scan every possible last word: pick a split point j; if dp[j] is true AND s[j..i-1] is in the dictionary, then dp[i] is also true. The first witness is enough - break out of the inner loop. dp[n] is the final answer.
A positive integer is a power of two iff its binary form has exactly one set bit (1, 10, 100, 1000…). The classic trick is `n & (n − 1) == 0`: subtracting one flips the lowest set bit AND all the zeros below it, so AND-ing with the original clears the only shared bit. If the result is zero, n had exactly one set bit - it's a power of two. Watch the bit rows: n's lone 1 disappears in the AND.
XOR has two magic properties: x ⊕ x = 0 (a value cancels itself) and x ⊕ 0 = x (zero is the identity). Folding XOR across every element in a list where every value appears twice EXCEPT one means all the duplicates cancel each other out and leave the unique value standing. The order doesn't matter - XOR is associative and commutative - so a single linear scan finds the answer in O(n) time, O(1) space.
Two counters - open and close - keep the string well-formed at every step. You can ALWAYS append '(' if you haven't used all n open parens. You can append ')' only if there are unmatched opens (close < open). Recursing on those two choices builds every valid combination exactly once. The number of valid combinations is the nth Catalan number: 1, 2, 5, 14, 42 for n = 1..5.
Every element is either IN the subset or OUT. Building the power set is a depth-first walk through that binary choice at each index: include nums[i] and recurse on i+1, then undo the include and recurse on i+1 again. Every leaf of that 2^n tree is one subset. Recording the running subset at the START of each call (before any choice) gives the canonical LC 78 output - the empty set first, the full set last.
A permutation is just a complete ordering of the input. Build one position at a time: for each unused element, place it next, recurse, then take it back out and try the next one. A boolean `used[]` (or a hash set) tells the recursion which elements are still available. When the current permutation has length n, record it and return - then unwind one level, mark the last-placed element as available again, and continue with the next candidate. n! permutations total.