Cyclic sort is an in-place, comparison-based sorting algorithm specifically designed for arrays containing numbers within a fixed, predefined range, such as 1 to N
or 0 to N-1
. It is highly efficient and straightforward, working by repeatedly placing elements in their correct, sorted positions through a series of swaps, effectively "cycling" through the array until every element is where it belongs.
Understanding the Core Concept
The fundamental idea behind cyclic sort is to ensure that each number X
in the array is located at its correct index. For an array of N
distinct numbers ranging from 1 to N
, the number 1
should be at index 0
, 2
at index 1
, and so on, up to N
at index N-1
. If the numbers range from 0 to N-1
, then 0
should be at index 0
, 1
at index 1
, and so forth.
The algorithm achieves this by iterating through the array. For each element, it checks if it's already in its correct position. If not, it swaps the element with the value that should be at its current position, continuing this process until the element is correctly placed. This creates a "cycle" of swaps until the element finally lands in its designated spot.
How Cyclic Sort Works (Algorithm Steps)
The cyclic sort algorithm proceeds iteratively, ensuring that each number finds its home:
- Initialize Pointer: Start with a pointer,
i
, at the beginning of the array (index 0). - Determine Correct Position: For the element
arr[i]
, calculate its correct index.- If numbers are from
1 to N
: The correct index forarr[i]
isarr[i] - 1
. - If numbers are from
0 to N-1
: The correct index forarr[i]
isarr[i]
.
- If numbers are from
- Check and Swap:
- If
arr[i]
is not at its correct index (i.e.,arr[i]
is not equal toarr[correct_index]
), swaparr[i]
with the element atarr[correct_index]
. This movesarr[i]
closer to its correct spot, and brings a new element toarr[i]
's current position to be evaluated. Crucially, the pointeri
does not increment after a swap because the new element atarr[i]
might also be out of place and needs to be processed. - If
arr[i]
is at its correct index, then this element is sorted. Increment the pointeri
to move to the next element.
- If
- Repeat: Continue steps 2 and 3 until the pointer
i
has traversed the entire array (i.e.,i < N
).
Key Characteristics and Efficiency
Cyclic sort is notable for its specific application and performance:
Characteristic | Description |
---|---|
Type | Comparison-based, In-place sorting algorithm. |
Time Complexity | O(N). Although elements might be swapped multiple times, each number is visited and moved towards its correct position at most a few times, resulting in a linear time complexity. |
Space Complexity | O(1). It only requires a constant amount of extra space for a few variables, as it sorts the array directly within its original memory location. |
Best For | Arrays where numbers are in a specific, consecutive range (e.g., 1 to N or 0 to N-1 ), and finding missing numbers, duplicates, or the smallest missing positive integer. |
For a broader understanding of how this algorithm fits within the landscape of various sorting techniques, you can explore more about sorting algorithms.
Example Walkthrough
Let's sort the array [3, 1, 5, 2, 4]
using cyclic sort. The numbers are from 1 to 5
.
- Initial Array:
[3, 1, 5, 2, 4]
- i = 0, arr[0] = 3:
- Correct index for
3
is3 - 1 = 2
. arr[0]
(value 3) is not atarr[2]
(value 5). Swaparr[0]
andarr[2]
.- Array becomes:
[5, 1, 3, 2, 4]
(i remains 0)
- Correct index for
- i = 0, arr[0] = 5:
- Correct index for
5
is5 - 1 = 4
. arr[0]
(value 5) is not atarr[4]
(value 4). Swaparr[0]
andarr[4]
.- Array becomes:
[4, 1, 3, 2, 5]
(i remains 0)
- Correct index for
- i = 0, arr[0] = 4:
- Correct index for
4
is4 - 1 = 3
. arr[0]
(value 4) is not atarr[3]
(value 2). Swaparr[0]
andarr[3]
.- Array becomes:
[2, 1, 3, 4, 5]
(i remains 0)
- Correct index for
- i = 0, arr[0] = 2:
- Correct index for
2
is2 - 1 = 1
. arr[0]
(value 2) is not atarr[1]
(value 1). Swaparr[0]
andarr[1]
.- Array becomes:
[1, 2, 3, 4, 5]
(i remains 0)
- Correct index for
- i = 0, arr[0] = 1:
- Correct index for
1
is1 - 1 = 0
. arr[0]
(value 1) is at its correct index (arr[0]
is 1). Incrementi
.
- Correct index for
- i = 1, arr[1] = 2:
- Correct index for
2
is2 - 1 = 1
. arr[1]
(value 2) is at its correct index (arr[1]
is 2). Incrementi
.
- Correct index for
- i = 2, arr[2] = 3:
- Correct index for
3
is3 - 1 = 2
. arr[2]
(value 3) is at its correct index (arr[2]
is 3). Incrementi
.
- Correct index for
- i = 3, arr[3] = 4:
- Correct index for
4
is4 - 1 = 3
. arr[3]
(value 4) is at its correct index (arr[3]
is 4). Incrementi
.
- Correct index for
- i = 4, arr[4] = 5:
- Correct index for
5
is5 - 1 = 4
. arr[4]
(value 5) is at its correct index (arr[4]
is 5). Incrementi
.
- Correct index for
- i = 5: The loop terminates as
i
is no longer less thanN
.
The array is now [1, 2, 3, 4, 5]
, which is sorted.
Advantages and Use Cases
Cyclic sort's unique properties make it particularly useful for specific problems:
- Efficiency: It offers optimal time complexity of O(N) for its target use case, making it very fast for large datasets within its defined constraints.
- In-Place: Its O(1) space complexity is a significant advantage, as it does not require additional memory proportional to the input size.
- Simplicity for Specific Problems: While not a general-purpose sorting algorithm like quicksort or merge sort, its simplicity shines when dealing with:
- Finding Missing Numbers: If a number is missing from the 1 to N range, its correct spot will be occupied by another number, or the range check will fail.
- Identifying Duplicate Numbers: If two numbers are the same, one will try to occupy a spot already taken by its duplicate.
- Finding the Smallest Missing Positive Number: A common variation where numbers outside the 1 to N range are ignored.
- Finding all Duplicates or Missing Numbers: Extensions of the basic algorithm can efficiently list all such discrepancies.