Skip to main content
Guides Skills and frameworks Divide and Conquer LeetCode Pattern Guide — Merge Sort, Quickselect, and Recursion
Skills and frameworks

Divide and Conquer LeetCode Pattern Guide — Merge Sort, Quickselect, and Recursion

11 min read · April 25, 2026

A practical LeetCode pattern guide for divide and conquer: master recursive contracts, merge sort variations, quickselect, tree recursion, complexity, and common interview traps.

Divide and Conquer LeetCode Pattern Guide — Merge Sort, Quickselect, and Recursion

This divide and conquer LeetCode pattern guide covers merge sort, quickselect, recursion templates, and the interview moves that make the pattern feel predictable instead of mystical. Divide and conquer problems ask you to split a problem into smaller independent pieces, solve each piece, and combine the answers. The trick is knowing what the recursive function returns and how the combine step works.

In interviews, divide and conquer is less about memorizing algorithms and more about communicating structure: base case, split, recursive call, merge, complexity, and edge cases. If you can make those parts explicit, most problems become manageable.

What divide and conquer means

A divide and conquer algorithm has three phases:

  1. Divide: break the input into smaller subproblems.
  2. Conquer: solve each subproblem, usually recursively.
  3. Combine: merge the subproblem results into the final answer.

Classic examples include merge sort, quicksort, quickselect, binary search, tree recursion, closest pair of points, counting inversions, and many segment-tree-style problems. On LeetCode, the pattern often appears when the input can be split by index range or tree subtree.

The common interview question is: "What should the recursive function return?" Once you answer that, the rest follows. For merge sort, it returns a sorted version of the range. For maximum subarray divide-and-conquer, it may return best prefix, best suffix, total sum, and best subarray. For tree diameter, it returns height while updating a global best diameter.

The divide and conquer interview template

Use this template before writing code:

  • State: What input does the recursive function receive? Usually left, right, a node, or a subarray.
  • Base case: What is the smallest solvable input?
  • Split: How do you divide the input? Middle index, pivot, children, quadrants?
  • Recursive result: What does each recursive call return?
  • Combine: How do you build the answer from child results?
  • Complexity: How many levels of recursion and how much work per level?

A verbal version: "I will define a helper on the inclusive range left to right. The base case is a range of length one. I split at mid, recursively solve left and right, then combine the two results. Since each level processes n total elements and there are log n levels, the time is O(n log n)."

That explanation is a strong opening for merge sort, inversion counting, range summaries, and many array recursion problems.

Merge sort: the cleanest divide and conquer example

Merge sort is the reference pattern because every phase is obvious.

  • Divide the array in half.
  • Sort the left half recursively.
  • Sort the right half recursively.
  • Merge the two sorted halves.

Why it matters in interviews: many problems borrow merge sort's structure but change the combine step. Counting inversions, counting smaller numbers after self, and range-sum counting all use the fact that the halves are sorted during merge.

For plain merge sort:

mergeSort(arr, left, right):
  if left >= right: return
  mid = (left + right) // 2
  mergeSort(arr, left, mid)
  mergeSort(arr, mid + 1, right)
  merge sorted halves

Complexity is O(n log n) time because there are log n levels and each level merges n total elements. Space is O(n) for the merge buffer, plus recursion stack O(log n).

The key interview move is to explain stability and merge logic. Stability means equal elements preserve relative order if the merge takes from the left side first when equal. That matters for sorting records by multiple keys.

Merge sort variations interviewers use

The merge step can count cross-boundary relationships that are hard to count otherwise.

| Problem type | Divide step | Combine insight | |---|---|---| | Count inversions | Sort left and right halves | During merge, when right value beats left value, count remaining left elements | | Count smaller after self | Sort indices by value | Track how many right-side values move before each left index | | Reverse pairs | Sort halves | Use two pointers to count pairs before merging | | Range sum count | Sort prefix sums | Count valid ranges across halves with sliding pointers |

These problems look different, but they share one idea: after recursive sorting, each half has structure, so the cross-boundary count can be done with two pointers instead of nested loops.

When stuck, ask: "If the left and right halves were already solved or sorted, what cross-boundary work remains?" That question often unlocks the solution.

Quickselect: divide and conquer without solving both sides

Quickselect finds the kth smallest or kth largest element. It uses the partition step from quicksort, but after partitioning, it recurses into only one side.

The structure:

  1. Choose a pivot.
  2. Partition the array so values less than pivot are on one side and greater values are on the other.
  3. Find the pivot's final index.
  4. If the pivot index is the target, return it.
  5. If target is left of pivot, recurse left.
  6. If target is right of pivot, recurse right.

Average time is O(n) because each partition scans the current range and usually discards about half the remaining elements. Worst-case time is O(n²) if pivots are consistently terrible. Randomized pivot selection reduces that risk.

Quickselect is ideal for:

  • Kth largest element in an array
  • Top K frequent elements when paired with bucket or heap decisions
  • Median finding
  • K closest points to origin
  • Selecting thresholds without fully sorting

The common mistake is sorting the whole array. Sorting is O(n log n). Quickselect can be O(n) average when you only need one boundary or kth element.

Quickselect details that prevent bugs

Partition code is where candidates lose time. Keep these rules straight:

  • Convert kth largest to target index: target = n - k in zero-indexed ascending order.
  • Randomize the pivot or use median-ish selection if worst-case matters.
  • Decide whether partition puts values < pivot left or <= pivot left, and be consistent.
  • Handle duplicates carefully; three-way partitioning can help when many values equal pivot.
  • Stop when left == right.

For "K closest points," partition by distance squared, not actual distance. Avoid square roots. After partitioning so the kth boundary is in place, return the first k points; they do not need to be sorted unless the prompt asks.

In interviews, explain that quickselect mutates the array. If the input must remain unchanged, copy it or choose a heap-based approach.

Recursion: base cases and return values

Divide and conquer depends on clean recursion. Most bugs come from vague return values. Before coding, write a sentence:

"My helper returns ____ for the subproblem ____."

Examples:

  • "Returns a sorted list for nums[left:right]."
  • "Returns the height of this subtree."
  • "Returns the maximum path sum starting at this node and extending downward."
  • "Returns a summary object with total sum, best prefix, best suffix, and best subarray."
  • "Returns whether this range can form a valid binary search tree."

Base cases follow from the return value. If the helper returns height, a null node returns 0 or -1 depending on your convention. If it returns a sorted list, an empty list returns empty and a one-element list returns itself. If it returns a range summary, a one-element range must initialize every field correctly.

A good interviewer will forgive minor syntax mistakes. They will not forgive a recursive function whose return contract changes halfway through.

Divide and conquer on trees

Trees are naturally recursive. Each node's answer often depends on left and right subtree answers.

Common examples:

| Problem | Helper returns | Combine step | |---|---|---| | Maximum depth | Height of subtree | 1 + max(left, right) | | Balanced binary tree | Height or failure marker | Check left/right height difference | | Diameter of binary tree | Height | Update best with left height + right height | | Maximum path sum | Best downward path | Update global best through node | | Validate BST | Min/max validity or range bounds | Enforce node constraints | | Lowest common ancestor | Candidate node | Combine left and right discoveries |

Tree divide and conquer differs from array divide and conquer because the split is already given: left child and right child. The challenge is usually deciding whether the answer should be returned upward, stored globally, or both.

For diameter, the returned value is height, but the final answer is diameter. That requires a global or external best. Say this explicitly: "The helper returns height to the parent, while I update a nonlocal best diameter at each node." This prevents confusion.

Range summary problems

Some harder divide and conquer problems require returning multiple pieces of information. Maximum subarray can be solved with Kadane's algorithm, but the divide-and-conquer version is a useful pattern.

For a range, return:

  • Total sum of the range
  • Best prefix sum
  • Best suffix sum
  • Best subarray sum

When combining left and right:

  • total = left.total + right.total
  • best prefix = max(left.best_prefix, left.total + right.best_prefix)
  • best suffix = max(right.best_suffix, right.total + left.best_suffix)
  • best subarray = max(left.best_subarray, right.best_subarray, left.best_suffix + right.best_prefix)

This pattern appears in segment trees, interval queries, and systems where summaries must be mergeable. The key is that each summary contains exactly the information needed by its parent. Not more, not less.

In interviews, this is a strong way to show maturity: "I need the recursive result to be composable, so I will return a small summary object."

Complexity analysis with recurrence intuition

Divide and conquer complexity often follows a recurrence. You do not need to be a Master Theorem wizard for most LeetCode interviews, but you should understand common shapes.

| Pattern | Recurrence | Complexity | |---|---|---| | Binary search | T(n)=T(n/2)+O(1) | O(log n) | | Merge sort | T(n)=2T(n/2)+O(n) | O(n log n) | | Quickselect average | T(n)=T(n/2)+O(n) | O(n) average | | Quicksort average | T(n)=2T(n/2)+O(n) | O(n log n) average | | Tree traversal | Visit each node once | O(n) | | Naive recursion with overlap | Recomputes states | Often exponential; use DP |

Always include recursion stack space. Balanced array recursion is O(log n). Tree recursion is O(h), where h is tree height; worst-case skewed tree is O(n). Merge sort also uses O(n) auxiliary space.

Common traps in divide and conquer LeetCode problems

The first trap is off-by-one range handling. Decide whether your range is inclusive [left, right] or half-open [left, right). Do not switch mid-solution. Half-open ranges simplify lengths; inclusive ranges are common in quickselect and binary search.

Second, candidates forget cross-boundary work. Solving left and right is not enough if the best answer spans the middle. Maximum subarray, inversion counting, and closest-pair-style problems all need cross-boundary logic.

Third, candidates recurse into both sides when one side is enough. Quickselect is efficient because it discards one side. Binary search is efficient for the same reason.

Fourth, candidates use global state without explaining it. Global best variables are fine for tree diameter and path sum, but state what the helper returns and what the global tracks.

Fifth, candidates miss duplicate handling in partition problems. If many values equal the pivot, naive two-way partition can degrade or loop incorrectly. Three-way partitioning is a good fallback.

Prep checklist for divide and conquer interviews

Practice this sequence:

  • Write the helper return contract before code.
  • Define base cases for empty, single element, and null node inputs.
  • Choose inclusive or half-open ranges and stick with it.
  • Identify the combine step before implementing recursion.
  • For sorted-half problems, look for two-pointer cross counts.
  • For kth-element problems, consider quickselect before full sort.
  • For tree problems, decide what returns upward and what updates globally.
  • Analyze time by levels and work per level.
  • Analyze space including recursion stack and merge buffers.
  • Test with tiny inputs: empty, one element, two elements, duplicates, sorted, reverse sorted.

A useful drill is to solve merge sort from memory, then count inversions, then kth largest, then tree diameter. Those four problems cover most of the mental moves.

How to talk about the pattern in interviews and resumes

In interviews, keep the language crisp:

  • "I can split the array and solve each half independently."
  • "The combine step is where the real logic lives."
  • "This helper returns a summary that is sufficient for the parent."
  • "Quickselect is better than sorting because we only need the kth boundary."
  • "The recursion stack is O(log n) if balanced, O(n) in the worst tree case."

On a resume, divide and conquer rarely appears as a literal phrase unless you are describing algorithms work. It can fit in bullets about search, ranking, data processing, or performance: "Implemented a divide-and-conquer ranking aggregation that reduced batch processing time from O(n²) comparisons to O(n log n)." The point is to connect the pattern to measurable performance, not to list LeetCode topics.

The interview-ready closing summary: "I will define the recursive contract, handle the base case, split the problem, solve subproblems, and make the combine step explicit. For merge sort-style problems the combine work drives O(n log n); for quickselect we recurse into one side for O(n) average; for trees the helper's return value and any global best must be clearly separated." That is the divide and conquer pattern in a form you can reuse under pressure.