The Long Way Around
An easy Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- easy
- Seniority
- L4
- Asked in
- Athenahealth
Problem
A batch job runs in a restricted runtime where the ordering built-ins are gone: no sorted(), no list.sort(), and no min() or max() to reach for. Given a list of integers nums, return them ordered smallest to largest.
Anyone can call the function. Order it by hand.
Example
Input:
nums = [1,1,3,4,5]
Output:
[1,1,3,4,5]
Worked solution and explanation
What this really is
Strip the costume and this is 'can you order a list when every ordering built-in is taken away.' sorted(), list.sort(), min(), and max() are all off the table, so you cannot even lean on min() to pluck the next smallest each pass. The whole problem is the loop you would normally never have to write: walk the list, and for each new element slide it left past everything larger than it. Anyone can name insertion sort. The trick lives in the inner loop boundary: you have to test j >= 0 BEFORE you touch nums[j], or you walk off the front of the list. Get that order backwards and it is an IndexError on the first element that belongs at position zero.
How to build it
Step 1: Pick the simplest sort you can defend
Insertion sort is the cleanest choice here: it is a handful of lines, sorts in place, and degrades gracefully. Selection sort works too, but with min() gone you would have to hand-scan for the smallest on every pass; insertion sort keeps the one comparison inline and finishes in a single pass over data that is already close to ordered.
Step 2: Hold the left side sorted
Everything to the left of the current index stays sorted at all times. Take the next element, remember it in key, and shift the sorted neighbors one slot to the right until you find the gap where key belongs. That invariant is the thing an interviewer actually wants to hear you say out loud.
Step 3: Land the element and return
Guard the inner loop with j >= 0 and nums[j] > key. Short-circuit evaluation means j >= 0 is checked first, so you never index a negative-then-invalid position. Drop key into nums[j + 1] once the loop stops. The list is mutated in place, so return nums.
The solution
def manual_sort(nums):
for i in range(1, len(nums)):
key = nums[i]
j = i - 1
while j >= 0 and nums[j] > key:
nums[j + 1] = nums[j]
j -= 1
nums[j + 1] = key
return numsCommon follow-up questions
- At what input size would you stop reaching for insertion sort and switch to merge sort or quicksort? (Tests awareness of when an O(n^2) algorithm is acceptable versus when O(n log n) is required.)
- What input makes this run in O(n), and why? (Tests understanding that nearly-sorted data makes insertion sort linear.)
- Is this sort stable as written, and what would break stability? (Tests knowledge that the strict > comparison already preserves the order of equal elements.)