Chapter 5: Recursion and Divide-and-Conquer Fundamentals
5.04Beginner7 topics22 min3 interactive animations

Divide and conquer

Divide and conquer solves a problem by splitting it into independent subproblems, solving each, and combining the answers. The split is only the start: the cost of combining and how evenly you split decide the running time.

Learning goals

  • Name the divide, conquer and combine steps of an algorithm
  • Explain why balanced splits matter
  • Read a recursion tree to estimate total work
  • Describe merge sort and quick sort as divide-and-conquer algorithms

Prerequisites

Recursion mechanicsMerge sort and quick sort (overview)

To count the votes in a large election, split the ballots among many teams, let each team count its pile, and add the totals. Counting a smaller pile is the same job as counting the whole thing, and combining is cheap.

5.04.1

Divide

Divide splits the input into smaller instances of the same problem. For an array, that usually means the two halves around mid; for a number, it means n / 2; for a list, the head and the rest.

The subproblems should be independent (they do not share work) and of the same kind as the original. If they overlap, you are in the territory of dynamic programming (Chapter 23).

5.04.2

Conquer

Conquer solves each subproblem recursively. When a subproblem is small enough, solve it directly: that is the base case. Libraries often switch to a simple method (such as insertion sort) at a small size because recursion has overhead.

In the animation, max(lo, hi) calls itself on both halves. Each box in the tree is one conquered subproblem, with its answer once it returns.

Worst

O(n)

Space

O(log n) stack

Divide and conquer: maximum of an array

Interactive · edit the input

Your input

Try

int[] arr · length 8

7
2
9
4
11
3
8
5
01234567
Right halfLeft halfMaximumOutside this call

Recursion tree · 1 call

max(0, 7)…
Running now
Call

Call max(a, 0, 7) on 8 elements.

Step 1 / 60
Java
1static int max(int[] a, int lo, int hi) {
2 if (lo == hi) return a[lo]; // one element: it is the max
3 int mid = lo + (hi - lo) / 2; // divide
4 int left = max(a, lo, mid); // conquer left half
5 int right = max(a, mid + 1, hi); // conquer right half
6 return Math.max(left, right); // combine
7}

Live state

1 calls0 comparisons

lo

0

hi

7

No condition evaluated on this step

Call stack (top first)

  1. max(0, 7)
Execution trace (dry run table)Show 60 steps
StepLineStateWhat happens
1L1lo=0 hi=7Call max(a, 0, 7) on 8 elements.
2L2lo=0 hi=7More than one element: divide.
3L3lo=0 mid=3 hi=7mid = 3. Left half [0..3], right half [4..7].
4L1lo=0 hi=3Call max(a, 0, 3) on 4 elements.
5L2lo=0 hi=3More than one element: divide.
6L3lo=0 mid=1 hi=3mid = 1. Left half [0..1], right half [2..3].
7L1lo=0 hi=1Call max(a, 0, 1) on 2 elements.
8L2lo=0 hi=1More than one element: divide.
9L3lo=0 mid=0 hi=1mid = 0. Left half [0..0], right half [1..1].
10L1lo=0 hi=0Call max(a, 0, 0) on 1 element.
11L2lo=0 hi=0One element: the maximum is a[0] = 7.
12L2return=7return 7.
13L4left=7Left half returned 7. Now the right half.
14L1lo=1 hi=1Call max(a, 1, 1) on 1 element.
15L2lo=1 hi=1One element: the maximum is a[1] = 2.
16L2return=2return 2.
17L6left=7 right=2 return=7Combine: the larger of 7 and 2 is 7. One comparison joins two answers.
18L4left=7Left half returned 7. Now the right half.
19L1lo=2 hi=3Call max(a, 2, 3) on 2 elements.
20L2lo=2 hi=3More than one element: divide.
21L3lo=2 mid=2 hi=3mid = 2. Left half [2..2], right half [3..3].
22L1lo=2 hi=2Call max(a, 2, 2) on 1 element.
23L2lo=2 hi=2One element: the maximum is a[2] = 9.
24L2return=9return 9.
25L4left=9Left half returned 9. Now the right half.
26L1lo=3 hi=3Call max(a, 3, 3) on 1 element.
27L2lo=3 hi=3One element: the maximum is a[3] = 4.
28L2return=4return 4.
29L6left=9 right=4 return=9Combine: the larger of 9 and 4 is 9. One comparison joins two answers.
30L6left=7 right=9 return=9Combine: the larger of 7 and 9 is 9. One comparison joins two answers.
31L4left=9Left half returned 9. Now the right half.
32L1lo=4 hi=7Call max(a, 4, 7) on 4 elements.
33L2lo=4 hi=7More than one element: divide.
34L3lo=4 mid=5 hi=7mid = 5. Left half [4..5], right half [6..7].
35L1lo=4 hi=5Call max(a, 4, 5) on 2 elements.
36L2lo=4 hi=5More than one element: divide.
37L3lo=4 mid=4 hi=5mid = 4. Left half [4..4], right half [5..5].
38L1lo=4 hi=4Call max(a, 4, 4) on 1 element.
39L2lo=4 hi=4One element: the maximum is a[4] = 11.
40L2return=11return 11.
41L4left=11Left half returned 11. Now the right half.
42L1lo=5 hi=5Call max(a, 5, 5) on 1 element.
43L2lo=5 hi=5One element: the maximum is a[5] = 3.
44L2return=3return 3.
45L6left=11 right=3 return=11Combine: the larger of 11 and 3 is 11. One comparison joins two answers.
46L4left=11Left half returned 11. Now the right half.
47L1lo=6 hi=7Call max(a, 6, 7) on 2 elements.
48L2lo=6 hi=7More than one element: divide.
49L3lo=6 mid=6 hi=7mid = 6. Left half [6..6], right half [7..7].
50L1lo=6 hi=6Call max(a, 6, 6) on 1 element.
51L2lo=6 hi=6One element: the maximum is a[6] = 8.
52L2return=8return 8.
53L4left=8Left half returned 8. Now the right half.
54L1lo=7 hi=7Call max(a, 7, 7) on 1 element.
55L2lo=7 hi=7One element: the maximum is a[7] = 5.
56L2return=5return 5.
57L6left=8 right=5 return=8Combine: the larger of 8 and 5 is 8. One comparison joins two answers.
58L6left=11 right=8 return=11Combine: the larger of 11 and 8 is 11. One comparison joins two answers.
59L6left=9 right=11 return=11Combine: the larger of 9 and 11 is 11. One comparison joins two answers.
60L6return=11The maximum is 11, found with 7 comparisons (n - 1, the same as a plain loop) and 15 calls. The point is the pattern: divide, conquer, combine.
5.04.3

Combine

Combine builds the answer to the whole problem from the answers to its parts. For the maximum it is one comparison; for merge sort it is an O(n) merge; for counting inversions it is a merge plus a count. For quick sort the combine step is empty, because all the work is in the divide (partition).

The cost of combining at each level is what the recurrence T(n) = a·T(n/b) + f(n) calls f(n). Cheap combines give linear algorithms; expensive ones may not help at all.

5.04.4

Balanced vs unbalanced split

If each split is balanced (halves), the tree has about log₂ n levels. If the split is lopsided (sizes n - 1 and 1), it has n levels and the algorithm behaves like a linear chain.

Merge sort always splits in the middle, so it is always O(n log n). Quick sort splits at the pivot, so a bad pivot gives O(n²). That is the whole difference between a worst case that is guaranteed good and one that depends on the data.

SplitDepth for n = 1,000,000Example
Halvesabout 20Merge sort, binary search
90% / 10%about 132Quick sort with a mediocre pivot
n - 1 / 11,000,000Quick sort on sorted input, last pivot
5.04.5

Recursion tree

Draw the tree of subproblems and add up the work per level. For merge sort: level 0 has 1 problem of size n, level 1 has 2 of size n / 2, level k has 2^k of size n / 2^k, so every level does n work in total over log₂ n levels.

The calculator in the next lesson computes these level totals for any a, b and d. Whether the top, the bottom or all levels dominate decides the answer.

LevelSubproblemsSize eachWork per level
01nn
12n / 2n
24n / 4n
k2^kn / 2^kn
log₂ nn1n
5.04.6

Merge sort intuition

Merge sort divides at the middle, conquers by sorting each half, and combines by merging two sorted halves in linear time. The recurrence is T(n) = 2·T(n/2) + O(n), which solves to O(n log n).

Its easy combine step is the key: merging two sorted lists is a single pass. Step through the animation and notice that all the sorting happens inside the merges, on the way back up.

Worst

O(n log n)

Space

O(n)

Merge sort (top-down)

Interactive · edit the input

Your input

Try

int[] arr · length 8

38
27
43
3
9
82
10
15
01234567
Being comparedSorted runOutside this call
Setup

Divide the 8 elements until single elements remain, then merge sorted runs back together.

Step 1 / 94
Java
1public static void mergeSort(int[] arr, int lo, int hi) {
2 if (hi - lo < 1) return;
3 int mid = lo + (hi - lo) / 2;
4 mergeSort(arr, lo, mid);
5 mergeSort(arr, mid + 1, hi);
6 merge(arr, lo, mid, hi);
7}
8
9static void merge(int[] arr, int lo, int mid, int hi) {
10 int[] tmp = new int[hi - lo + 1];
11 int i = lo, j = mid + 1, k = 0;
12 while (i <= mid && j <= hi) {
13 if (arr[i] <= arr[j]) tmp[k++] = arr[i++];
14 else tmp[k++] = arr[j++];
15 }
16 while (i <= mid) tmp[k++] = arr[i++];
17 while (j <= hi) tmp[k++] = arr[j++];
18 System.arraycopy(tmp, 0, arr, lo, tmp.length);
19}

Live state

0 comparisons

n

8

No condition evaluated on this step
Execution trace (dry run table)Show 94 steps
StepLineStateWhat happens
1L1n=8Divide the 8 elements until single elements remain, then merge sorted runs back together.
2L1lo=0 hi=7 size=8Enter mergeSort(arr, 0, 7) on 8 elements.
3L2lo=0 hi=7More than one element, so split in half.
4L3lo=0 mid=3 hi=7mid = 3. Left half [0..3], right half [4..7].
5L4lo=0 hi=3 size=4Enter mergeSort(arr, 0, 3) on 4 elements.
6L2lo=0 hi=3More than one element, so split in half.
7L3lo=0 mid=1 hi=3mid = 1. Left half [0..1], right half [2..3].
8L4lo=0 hi=1 size=2Enter mergeSort(arr, 0, 1) on 2 elements.
9L2lo=0 hi=1More than one element, so split in half.
10L3lo=0 mid=0 hi=1mid = 0. Left half [0..0], right half [1..1].
11L4lo=0 hi=0 size=1Enter mergeSort(arr, 0, 0) on 1 element.
12L2lo=0 hi=0Base case: one element is already sorted.
13L5lo=1 hi=1 size=1Enter mergeSort(arr, 1, 1) on 1 element.
14L2lo=1 hi=1Base case: one element is already sorted.
15L10lo=0 mid=0 hi=1 i=0 j=1 k=0Allocate tmp for 2 elements. Left run [0..0] and right run [1..1] are each already sorted.
16L13lo=0 mid=0 hi=1 i=0 j=1 k=0The right head is strictly smaller, so take it.
17L14lo=0 mid=0 hi=1 i=0 j=2 k=1tmp[0] = 27.
18L16lo=0 mid=0 hi=1 i=1 j=2 k=2The left run still has 1 element. They are already sorted and no larger run remains, so copy them all.
19L18lo=0 mid=0 hi=1 i=1 j=2 k=2Copy tmp back into arr[0..1]. That range is now sorted.
20L5lo=2 hi=3 size=2Enter mergeSort(arr, 2, 3) on 2 elements.
21L2lo=2 hi=3More than one element, so split in half.
22L3lo=2 mid=2 hi=3mid = 2. Left half [2..2], right half [3..3].
23L4lo=2 hi=2 size=1Enter mergeSort(arr, 2, 2) on 1 element.
24L2lo=2 hi=2Base case: one element is already sorted.
25L5lo=3 hi=3 size=1Enter mergeSort(arr, 3, 3) on 1 element.
26L2lo=3 hi=3Base case: one element is already sorted.
27L10lo=2 mid=2 hi=3 i=2 j=3 k=0Allocate tmp for 2 elements. Left run [2..2] and right run [3..3] are each already sorted.
28L13lo=2 mid=2 hi=3 i=2 j=3 k=0The right head is strictly smaller, so take it.
29L14lo=2 mid=2 hi=3 i=2 j=4 k=1tmp[0] = 3.
30L16lo=2 mid=2 hi=3 i=3 j=4 k=2The left run still has 1 element. They are already sorted and no larger run remains, so copy them all.
31L18lo=2 mid=2 hi=3 i=3 j=4 k=2Copy tmp back into arr[2..3]. That range is now sorted.
32L10lo=0 mid=1 hi=3 i=0 j=2 k=0Allocate tmp for 4 elements. Left run [0..1] and right run [2..3] are each already sorted.
33L13lo=0 mid=1 hi=3 i=0 j=2 k=0The right head is strictly smaller, so take it.
34L14lo=0 mid=1 hi=3 i=0 j=3 k=1tmp[0] = 3.
35L13lo=0 mid=1 hi=3 i=0 j=3 k=1The left head is not larger, so take it. Using <= (left wins ties) is what makes merge sort stable.
36L13lo=0 mid=1 hi=3 i=1 j=3 k=2tmp[1] = 27.
37L13lo=0 mid=1 hi=3 i=1 j=3 k=2The left head is not larger, so take it. Using <= (left wins ties) is what makes merge sort stable.
38L13lo=0 mid=1 hi=3 i=2 j=3 k=3tmp[2] = 38.
39L17lo=0 mid=1 hi=3 i=2 j=4 k=4The right run still has 1 element. They are already sorted and no larger run remains, so copy them all.
40L18lo=0 mid=1 hi=3 i=2 j=4 k=4Copy tmp back into arr[0..3]. That range is now sorted.
41L5lo=4 hi=7 size=4Enter mergeSort(arr, 4, 7) on 4 elements.
42L2lo=4 hi=7More than one element, so split in half.
43L3lo=4 mid=5 hi=7mid = 5. Left half [4..5], right half [6..7].
44L4lo=4 hi=5 size=2Enter mergeSort(arr, 4, 5) on 2 elements.
45L2lo=4 hi=5More than one element, so split in half.
46L3lo=4 mid=4 hi=5mid = 4. Left half [4..4], right half [5..5].
47L4lo=4 hi=4 size=1Enter mergeSort(arr, 4, 4) on 1 element.
48L2lo=4 hi=4Base case: one element is already sorted.
49L5lo=5 hi=5 size=1Enter mergeSort(arr, 5, 5) on 1 element.
50L2lo=5 hi=5Base case: one element is already sorted.
51L10lo=4 mid=4 hi=5 i=4 j=5 k=0Allocate tmp for 2 elements. Left run [4..4] and right run [5..5] are each already sorted.
52L13lo=4 mid=4 hi=5 i=4 j=5 k=0The left head is not larger, so take it. Using <= (left wins ties) is what makes merge sort stable.
53L13lo=4 mid=4 hi=5 i=5 j=5 k=1tmp[0] = 9.
54L17lo=4 mid=4 hi=5 i=5 j=6 k=2The right run still has 1 element. They are already sorted and no larger run remains, so copy them all.
55L18lo=4 mid=4 hi=5 i=5 j=6 k=2Copy tmp back into arr[4..5]. That range is now sorted.
56L5lo=6 hi=7 size=2Enter mergeSort(arr, 6, 7) on 2 elements.
57L2lo=6 hi=7More than one element, so split in half.
58L3lo=6 mid=6 hi=7mid = 6. Left half [6..6], right half [7..7].
59L4lo=6 hi=6 size=1Enter mergeSort(arr, 6, 6) on 1 element.
60L2lo=6 hi=6Base case: one element is already sorted.
61L5lo=7 hi=7 size=1Enter mergeSort(arr, 7, 7) on 1 element.
62L2lo=7 hi=7Base case: one element is already sorted.
63L10lo=6 mid=6 hi=7 i=6 j=7 k=0Allocate tmp for 2 elements. Left run [6..6] and right run [7..7] are each already sorted.
64L13lo=6 mid=6 hi=7 i=6 j=7 k=0The left head is not larger, so take it. Using <= (left wins ties) is what makes merge sort stable.
65L13lo=6 mid=6 hi=7 i=7 j=7 k=1tmp[0] = 10.
66L17lo=6 mid=6 hi=7 i=7 j=8 k=2The right run still has 1 element. They are already sorted and no larger run remains, so copy them all.
67L18lo=6 mid=6 hi=7 i=7 j=8 k=2Copy tmp back into arr[6..7]. That range is now sorted.
68L10lo=4 mid=5 hi=7 i=4 j=6 k=0Allocate tmp for 4 elements. Left run [4..5] and right run [6..7] are each already sorted.
69L13lo=4 mid=5 hi=7 i=4 j=6 k=0The left head is not larger, so take it. Using <= (left wins ties) is what makes merge sort stable.
70L13lo=4 mid=5 hi=7 i=5 j=6 k=1tmp[0] = 9.
71L13lo=4 mid=5 hi=7 i=5 j=6 k=1The right head is strictly smaller, so take it.
72L14lo=4 mid=5 hi=7 i=5 j=7 k=2tmp[1] = 10.
73L13lo=4 mid=5 hi=7 i=5 j=7 k=2The right head is strictly smaller, so take it.
74L14lo=4 mid=5 hi=7 i=5 j=8 k=3tmp[2] = 15.
75L16lo=4 mid=5 hi=7 i=6 j=8 k=4The left run still has 1 element. They are already sorted and no larger run remains, so copy them all.
76L18lo=4 mid=5 hi=7 i=6 j=8 k=4Copy tmp back into arr[4..7]. That range is now sorted.
77L10lo=0 mid=3 hi=7 i=0 j=4 k=0Allocate tmp for 8 elements. Left run [0..3] and right run [4..7] are each already sorted.
78L13lo=0 mid=3 hi=7 i=0 j=4 k=0The left head is not larger, so take it. Using <= (left wins ties) is what makes merge sort stable.
79L13lo=0 mid=3 hi=7 i=1 j=4 k=1tmp[0] = 3.
80L13lo=0 mid=3 hi=7 i=1 j=4 k=1The right head is strictly smaller, so take it.
81L14lo=0 mid=3 hi=7 i=1 j=5 k=2tmp[1] = 9.
82L13lo=0 mid=3 hi=7 i=1 j=5 k=2The right head is strictly smaller, so take it.
83L14lo=0 mid=3 hi=7 i=1 j=6 k=3tmp[2] = 10.
84L13lo=0 mid=3 hi=7 i=1 j=6 k=3The right head is strictly smaller, so take it.
85L14lo=0 mid=3 hi=7 i=1 j=7 k=4tmp[3] = 15.
86L13lo=0 mid=3 hi=7 i=1 j=7 k=4The left head is not larger, so take it. Using <= (left wins ties) is what makes merge sort stable.
87L13lo=0 mid=3 hi=7 i=2 j=7 k=5tmp[4] = 27.
88L13lo=0 mid=3 hi=7 i=2 j=7 k=5The left head is not larger, so take it. Using <= (left wins ties) is what makes merge sort stable.
89L13lo=0 mid=3 hi=7 i=3 j=7 k=6tmp[5] = 38.
90L13lo=0 mid=3 hi=7 i=3 j=7 k=6The left head is not larger, so take it. Using <= (left wins ties) is what makes merge sort stable.
91L13lo=0 mid=3 hi=7 i=4 j=7 k=7tmp[6] = 43.
92L17lo=0 mid=3 hi=7 i=4 j=8 k=8The right run still has 1 element. They are already sorted and no larger run remains, so copy them all.
93L18lo=0 mid=3 hi=7 i=4 j=8 k=8Copy tmp back into arr[0..7]. That range is now sorted.
94L6Sorted with 17 comparisons. About n log n comparisons, whatever the input order.
5.04.7

Quick sort intuition

Quick sort puts the work in the divide: partition around a pivot so that everything smaller is on the left and everything larger on the right. The conquer step sorts both sides, and the combine step is empty, because the pieces are already in the right order.

Its running time depends entirely on how balanced the partitions are. Change the Pivot option and run the sorted-input preset to watch the tree become a chain.

Average

O(n log n)

Worst

O(n²)

Space

O(log n)

Quick sort (Lomuto partition)

Interactive · edit the input

Your input

Try

int[] arr · length 8

38
27
43
3
9
82
10
15
01234567
PivotBeing comparedLess than pivotFinal positionOutside this call
Setup

Pick a pivot, partition around it, then sort each side. Pivot strategy: last element.

Step 1 / 61
Java
1public static void quickSort(int[] arr, int lo, int hi) {
2 if (lo >= hi) return;
3 int p = partition(arr, lo, hi);
4 quickSort(arr, lo, p - 1);
5 quickSort(arr, p + 1, hi);
6}
7
8static int partition(int[] arr, int lo, int hi) {
9 movePivotToEnd(arr, lo, hi); // strategy: last, first, middle, median of 3
10 int pivot = arr[hi];
11 int i = lo; // arr[lo..i-1] < pivot
12 for (int j = lo; j < hi; j++) {
13 if (arr[j] < pivot) {
14 swap(arr, i, j);
15 i++;
16 }
17 }
18 swap(arr, i, hi); // pivot to its final place
19 return i;
20}

Live state

0 comparisons0 swaps

n

8

No condition evaluated on this step
Execution trace (dry run table)Show 61 steps
StepLineStateWhat happens
1L1n=8Pick a pivot, partition around it, then sort each side. Pivot strategy: last element.
2L1lo=0 hi=7Enter quickSort(arr, 0, 7).
3L2lo=0 hi=7Two or more elements, so partition.
4L9lo=0 hi=7Pivot strategy: last element. The pivot is already at arr[7].
5L11pivot=15 i=0pivot = 15. i marks where the next value smaller than the pivot will go.
6L13pivot=15 i=0 j=0Not smaller: leave it for the right region.
7L13pivot=15 i=0 j=1Not smaller: leave it for the right region.
8L13pivot=15 i=0 j=2Not smaller: leave it for the right region.
9L13pivot=15 i=0 j=3Smaller than the pivot: it belongs in the left region.
10L14pivot=15 i=1 j=3Swap arr[0] and arr[3], then i = 1.
11L13pivot=15 i=1 j=4Smaller than the pivot: it belongs in the left region.
12L14pivot=15 i=2 j=4Swap arr[1] and arr[4], then i = 2.
13L13pivot=15 i=2 j=5Not smaller: leave it for the right region.
14L13pivot=15 i=2 j=6Smaller than the pivot: it belongs in the left region.
15L14pivot=15 i=3 j=6Swap arr[2] and arr[6], then i = 3.
16L18pivot=15 p=3Swap the pivot into index 3. Everything left of it is < 15, everything right is >= 15, and 15 will never move again.
17L4lo=0 hi=2Enter quickSort(arr, 0, 2).
18L2lo=0 hi=2Two or more elements, so partition.
19L9lo=0 hi=2Pivot strategy: last element. The pivot is already at arr[2].
20L11pivot=10 i=0pivot = 10. i marks where the next value smaller than the pivot will go.
21L13pivot=10 i=0 j=0Smaller than the pivot: it belongs in the left region.
22L14pivot=10 i=1 j=0arr[0] is already in place; i advances to 1.
23L13pivot=10 i=1 j=1Smaller than the pivot: it belongs in the left region.
24L14pivot=10 i=2 j=1arr[1] is already in place; i advances to 2.
25L18pivot=10 p=2Swap the pivot into index 2. Everything left of it is < 10, everything right is >= 10, and 10 will never move again.
26L4lo=0 hi=1Enter quickSort(arr, 0, 1).
27L2lo=0 hi=1Two or more elements, so partition.
28L9lo=0 hi=1Pivot strategy: last element. The pivot is already at arr[1].
29L11pivot=9 i=0pivot = 9. i marks where the next value smaller than the pivot will go.
30L13pivot=9 i=0 j=0Smaller than the pivot: it belongs in the left region.
31L14pivot=9 i=1 j=0arr[0] is already in place; i advances to 1.
32L18pivot=9 p=1Swap the pivot into index 1. Everything left of it is < 9, everything right is >= 9, and 9 will never move again.
33L4lo=0 hi=0Enter quickSort(arr, 0, 0).
34L2lo=0 hi=0Zero or one element: already sorted.
35L5lo=2 hi=1Enter quickSort(arr, 2, 1).
36L2lo=2 hi=1Zero or one element: already sorted.
37L5lo=3 hi=2Enter quickSort(arr, 3, 2).
38L2lo=3 hi=2Zero or one element: already sorted.
39L5lo=4 hi=7Enter quickSort(arr, 4, 7).
40L2lo=4 hi=7Two or more elements, so partition.
41L9lo=4 hi=7Pivot strategy: last element. The pivot is already at arr[7].
42L11pivot=38 i=4pivot = 38. i marks where the next value smaller than the pivot will go.
43L13pivot=38 i=4 j=4Smaller than the pivot: it belongs in the left region.
44L14pivot=38 i=5 j=4arr[4] is already in place; i advances to 5.
45L13pivot=38 i=5 j=5Not smaller: leave it for the right region.
46L13pivot=38 i=5 j=6Not smaller: leave it for the right region.
47L18pivot=38 p=5Swap the pivot into index 5. Everything left of it is < 38, everything right is >= 38, and 38 will never move again.
48L4lo=4 hi=4Enter quickSort(arr, 4, 4).
49L2lo=4 hi=4Zero or one element: already sorted.
50L5lo=6 hi=7Enter quickSort(arr, 6, 7).
51L2lo=6 hi=7Two or more elements, so partition.
52L9lo=6 hi=7Pivot strategy: last element. The pivot is already at arr[7].
53L11pivot=82 i=6pivot = 82. i marks where the next value smaller than the pivot will go.
54L13pivot=82 i=6 j=6Smaller than the pivot: it belongs in the left region.
55L14pivot=82 i=7 j=6arr[6] is already in place; i advances to 7.
56L18pivot=82 p=7Swap the pivot into index 7. Everything left of it is < 82, everything right is >= 82, and 82 will never move again.
57L4lo=6 hi=6Enter quickSort(arr, 6, 6).
58L2lo=6 hi=6Zero or one element: already sorted.
59L5lo=8 hi=7Enter quickSort(arr, 8, 7).
60L2lo=8 hi=7Zero or one element: already sorted.
61L6Sorted with 14 comparisons and 5 swaps.

Practice ladder

Now try it yourself

Easy

  • Find the minimum of an array by divide and conquer
  • Count the elements equal to x by halving
  • Compute the sum of an array recursively by halves

Medium

  • Maximum subarray sum by divide and conquer (crossing sum)
  • Count inversions with merge sort
  • Closest pair of points (outline)

Advanced

  • Karatsuba multiplication
  • Strassen matrix multiplication recurrence
  • Find the median of two sorted arrays

Key takeaways

  • Divide and conquer = split, solve independently, combine.
  • Balanced splits give logarithmic depth; lopsided splits give linear depth.
  • Add up the work per level of the recursion tree to find the running time.