Problem:
Given a list of numbers with only 3 unique numbers (1, 2, 3), sort the list in O(n) time.
Example 1:
Input: [3, 3, 2, 1, 3, 2, 1] Output: [1, 1, 2, 2, 3, 3, 3]
def sortNums(nums): # Fill this in. print sortNums([3, 3, 2, 1, 3, 2, 1]) # [1, 1, 2, 2, 3, 3, 3]
Challenge: Try sorting the list using constant space.
Solution 1:
Here we count the number of 1, 2, and 3, in the list, and then create a new list with the same numbers of 1, 2, and 3.
def sortNums(nums): num_one = 0 num_two = 0 num_three = 0 for n in nums: if n == 1: num_one += 1 elif n == 2: num_two += 1 elif n == 3: num_three += 1 return [1] * num_one + [2] * num_two + [3] * num_three print sortNums([3, 3, 2, 1, 3, 2, 1]) # [1, 1, 2, 2, 3, 3, 3]
Solution 2:
We can sort the list in place if there are only 3 unique numbers. The general idea is to swap the lowest number to the leftmost index that is not sorted yet, and swap the highest number to the rightmost index that is not sorted yet.
In this case, we have one_idx that represents the leftmost index that is not sorted (so everything left of one_idx is a 1), and three_idx that represents the rightmost index that is not sorted( so everything right of three_idx is a 3).
We go through each element in the list and swap with one_idx if we see a 1, or swap with the three_idx if we see a 3. If the element is a 2 it is in the middle of the list already and no action needs to be done.
This code has a time complexity of O(n), as we only iterate through each element in the list once (once elements are swapped away we will never ‘see’ them again). The space complexity is O(1) as we are just swapping elements in the list.
def sortNums(nums): one_idx = 0 # Represents the leftmost index that is not 0 three_idx = len(nums) - 1 # Represents the rightmost index that is not 2 idx = 0 # Represents the index that we are checking while idx <= three_idx: if nums[idx] == 1: # Swap numbers with leftmost index # so all numbers up to one_idx are all 1 nums[idx], nums[one_idx] = nums[one_idx], nums[idx] idx += 1 one_idx += 1 elif nums[idx] == 2: # If index is 2, it means list is in order, check next number idx += 1 elif nums[idx] == 3: # Swap numbers with rightmost index # so all numbers after three_idx are all 3 nums[idx], nums[three_idx] = nums[three_idx], nums[idx] three_idx -= 1 return nums print sortNums([3, 3, 2, 1, 3, 2, 1]) # [1, 1, 2, 2, 3, 3, 3]
4 comments On [Solution] Sorting a list with three unique numbers
Solution 2 does not work for this input {3, 1, 2, 1, 3, 2, 1}
Pingback: Sorting Algorithm with complexity of O(n) time and O(1) space? – Chia Lin's Journey ()
Why not just use sorted() ?
its slower