Given an array nums
with n
objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.
We will use the integers 0
, 1
, and 2
to represent the color red, white, and blue, respectively.
You must solve this problem without using the library's sort function.
Example 1:
Input: nums = [2,0,2,1,1,0] Output: [0,0,1,1,2,2]
Example 2:
Input: nums = [2,0,1] Output: [0,1,2]
Constraints:
n == nums.length
1 <= n <= 300
nums[i]
is either 0
, 1
, or 2
.Follow up: Could you come up with a one-pass algorithm using 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:
The simplest way to solve this is to first count how many of each color you have. Once you know the counts, you can rebuild the entire collection from scratch in the correct order: all the reds, then all the whites, followed by all the blues.
Here's how the algorithm would work step-by-step:
class Solution:
def sortColors(self, nums: list[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
# This approach uses two passes: one to count the colors and another to overwrite the array.
red_count = 0
white_count = 0
blue_count = 0
for color in nums:
if color == 0:
red_count += 1
elif color == 1:
white_count += 1
else:
blue_count += 1
# Overwrite the original array with the correct number of 0s (reds).
for index in range(red_count):
nums[index] = 0
# Continue overwriting where the reds left off with the 1s (whites).
for index in range(red_count, red_count + white_count):
nums[index] = 1
# Finally, fill the remaining part of the array with 2s (blues).
for index in range(red_count + white_count, len(nums)):
nums[index] = 2
The most efficient strategy is to sort the items in a single pass without using any extra storage. We do this by imagining three sections for red, white, and blue, and then moving items to their correct section one by one.
Here's how the algorithm would work step-by-step:
def sort_colors(colors):
red_section_end = 0
blue_section_start = len(colors) - 1
current_index = 0
while current_index <= blue_section_start:
# If the current element is red (0), it belongs in the front partition.
if colors[current_index] == 0:
colors[current_index], colors[red_section_end] = colors[red_section_end], colors[current_index]
red_section_end += 1
current_index += 1
# If the current element is blue (2), it must be moved to the end partition.
elif colors[current_index] == 2:
colors[current_index], colors[blue_section_start] = colors[blue_section_start], colors[current_index]
blue_section_start -= 1
# If the element is white (1), it's in the correct middle partition, so we just advance.
else:
current_index += 1
Case | How to Handle |
---|---|
Input array is null or empty | The algorithm should handle this gracefully by simply returning without modification as there is nothing to sort. |
Input array has only one element | The array is already sorted by definition, so the algorithm should terminate immediately without making any changes. |
Input array contains only one or two distinct colors | The one-pass algorithm correctly handles this by partitioning the array based on the colors that are present. |
Input array consists of all identical elements (e.g., all 0s, all 1s, or all 2s) | The pointers in the one-pass solution will move appropriately, resulting in the correct, unchanged sorted array. |
Input array is already sorted | The algorithm will perform a single pass without any swaps, efficiently confirming the sorted state. |
Input array is sorted in reverse order (e.g., [2, 2, 1, 0, 0]) | The algorithm will perform the maximum number of swaps but will still correctly sort the array in a single pass. |
Large input array (approaching memory or time limits) | The one-pass, in-place solution has O(n) time and O(1) space complexity, ensuring it scales efficiently for large inputs. |
Input contains only 0s and 2s with no 1s | The middle pointer will correctly increment or the right pointer will decrement after swaps, leaving no space for the non-existent 1s. |