Divide and conquer is an algorithm design strategy built on a simple idea: break a big problem into smaller subproblems of the same type, solve each one independently (often by recursing), and then combine their results into the answer for the original problem. It's one of the oldest and most powerful algorithmic patterns, and you've almost certainly already used algorithms built on it — merge sort and binary search are both classic examples.

The pattern always has three steps, which is why it's easy to recognize once you know to look for it:

The Three Steps

  1. Divide — split the problem into smaller subproblems of the same kind.
  2. Conquer — solve each subproblem, typically by recursing until the subproblem is trivially small (the base case).
  3. Combine — merge the subproblem results together into a solution for the original, larger problem.

Example: Merge Sort

Merge sort is divide and conquer in its purest form. To sort an array: divide it in half, conquer each half by recursively sorting it, then combine the two sorted halves by merging them into one sorted array.

def merge_sort(arr):
    if len(arr) <= 1:
        return arr  # base case: a single element is already "sorted"

    # Divide
    mid = len(arr) // 2
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])

    # Combine
    return merge(left, right)

def merge(left, right):
    result = []
    i = j = 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i]); i += 1
        else:
            result.append(right[j]); j += 1
    result.extend(left[i:])
    result.extend(right[j:])
    return result

print(merge_sort([38, 27, 43, 3, 9, 82, 10]))

Output:

[3, 9, 10, 27, 38, 43, 82]

Each half is sorted completely independently of the other — neither recursive call needs to know anything about what's happening in the other branch. That independence is exactly what makes divide and conquer so effective: it turns one large problem into smaller, self-contained ones. See the full breakdown in our dedicated Merge Sort guide.

Example: Binary Search

Binary search is also divide and conquer, though it only ever recurses into one half instead of both — compare the target to the middle element, then throw away the half that can't possibly contain it, and repeat on the remaining half. Because it eliminates half the remaining problem at every step rather than solving both halves, it runs in O(log n) instead of O(n log n).

Divide and Conquer vs Dynamic Programming

Both techniques break a problem into subproblems — the key difference is whether those subproblems overlap. In merge sort, the left half and right half of the array are completely independent; solving one tells you nothing about the other, so there's nothing to reuse. Dynamic programming is for the opposite situation — problems where the same subproblem gets solved repeatedly (like naive recursive Fibonacci recomputing the same values over and over), where caching previous results turns an exponential algorithm into a linear one. If your subproblems never overlap, divide and conquer is the right lens; if they do, DP usually wins.