You are given an array nums
containing n
integers where each integer represents a color: 0 (red), 1 (white), or 2 (blue). Your task is to sort the array in-place such that all elements of the same color are adjacent, with the colors appearing in the order red, white, and blue. You are not allowed to use any library sorting functions.
For example:
nums = [2, 0, 2, 1, 1, 0]
should be sorted to [0, 0, 1, 1, 2, 2]
.nums = [2, 0, 1]
should be sorted to [0, 1, 2]
.Consider the following constraints:
n
(the length of nums
) is between 1 and 300 (inclusive).nums[i]
is either 0, 1, or 2.Can you implement an efficient algorithm to solve this sorting problem?
Follow-up question: Can you solve it using a one-pass algorithm with only constant extra space?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
Imagine you have a bag of red, white, and blue marbles and want to sort them by color. The brute force way is to simply count how many of each color you have, without actually rearranging the marbles.
Here's how the algorithm would work step-by-step:
def sort_colors_brute_force(colors):
red_count = 0
white_count = 0
blue_count = 0
# Count the occurrences of each color
for color in colors:
if color == 0:
red_count += 1
elif color == 1:
white_count += 1
else:
blue_count += 1
# Overwrite the original array
# Rebuild the array with sorted colors
index = 0
for _ in range(red_count):
colors[index] = 0
index += 1
# Populate with white colors
for _ in range(white_count):
colors[index] = 1
index += 1
# Finally populate with blue
for _ in range(blue_count):
colors[index] = 2
index += 1
The most efficient way to sort these colors is to think of them as needing to be moved into their correct sections. We use three 'pointers' to keep track of where each color section should start.
Here's how the algorithm would work step-by-step:
def sort_colors(colors):
start_of_middle_section = 0
end_of_middle_section = len(colors) - 1
current_index = 0
while current_index <= end_of_middle_section:
if colors[current_index] == 0:
# Move 0 to the beginning
colors[current_index], colors[start_of_middle_section] = colors[start_of_middle_section], colors[current_index]
start_of_middle_section += 1
current_index += 1
elif colors[current_index] == 1:
# 1 is in the correct section
current_index += 1
else:
# Move 2 to the end
colors[current_index], colors[end_of_middle_section] = colors[end_of_middle_section], colors[current_index]
end_of_middle_section -= 1
# Re-evaluate swapped element
continue
Case | How to Handle |
---|---|
Null or empty input array | Return immediately without modification since there's nothing to sort. |
Array with one element | No sorting is needed; the array is already sorted. |
Array with only 0s | Algorithm should still execute correctly, leaving the array unchanged. |
Array with only 1s | Algorithm should still execute correctly, leaving the array unchanged. |
Array with only 2s | Algorithm should still execute correctly, leaving the array unchanged. |
Array already sorted (0s, 1s, 2s) | Algorithm should still execute correctly, without making unnecessary swaps. |
Array in reverse sorted order (2s, 1s, 0s) | Algorithm should handle this case efficiently by performing the necessary swaps. |
Array containing a large number of elements with a skewed distribution (e.g., mostly 0s) | The chosen algorithm (e.g., Dutch National Flag) should maintain good performance even with skewed distributions. |