The Custom Sort String problem is a classic coding interview question because it tests whether you can follow a custom ordering rule instead of relying on default sorting. Interviewers use it to see how you handle real constraints like duplicates in s and extra characters that aren’t mentioned in order.
Problem statement
You are given two lowercase strings: order, which lists some characters in a special “preferred” ordering (with no repeats), and s, which contains characters you can rearrange. Your task is to permute s so that any characters that appear in order show up in s following the same relative ordering as in order.
The tricky part is that s can contain repeated characters and also characters not mentioned in order. Those “unspecified” characters are allowed anywhere, so you must enforce the custom ordering only for the subset of characters controlled by order while still returning a valid permutation of the entire s.
Constraints:
- 1 <=
order.length<= 26 - 1 <=
s.length<= 200 orderandsconsists of lowercase English letters.- All characters of
orderare unique.
Examples
| Input | Output | Explanation | |
| order | s | ||
| order = “yxw” | s = “wxyz” | "yxwz" | The relative order among “y”, “x”, “w” must follow “y” → “x” → “w”. “z” is not in order, so it can be placed anywhere (e.g., at the end here). |
| order = “bcafg” | s = “wxyz” | "bcad" | Characters from s that appear in order are “b”, “c”, “a”, and they must keep the order “b” → “c” → “a”. “d” is not in order, so its position is flexible. |
Naive approach: Trying all permutations
One straightforward idea is to generate permutations of s and return the first one that satisfies the ordering rule. But s can be up to length 200, and the number of permutations grows astronomically. Even if you try to “sort” s by comparing characters using order, doing it with repeated lookups and custom comparisons can still be clumsy and easy to get wrong with duplicates.
A better way is to avoid re-checking the relative order repeatedly. Instead, we should build the result directly from character frequencies, so each character is placed exactly as many times as it appears, with no wasted work.
Optimized approach: Custom Order via Frequency Count
A better way to solve this problem is to count how many times each character appears in s. Then, output characters in the exact sequence specified by order, repeating each as many times as its frequency. After that, append all remaining characters (those not present in order) in any order, again based on their frequencies.
This works cleanly even with repeated characters because we never compare individual positions or try to “move” letters around; we simply emit the correct number of each character in a valid sequence.
Why does this work even with unconstrained characters
Characters not in order do not participate in any required relative ordering, so they can appear anywhere without breaking the rule. By appending them after all constrained characters, we automatically satisfy the constraint, while still using every character from s exactly once.
Solution steps
- Count characters in
sby building a frequency mapcountswherecounts[c]= how many times charactercappears ins. - Create an empty list
outto collect pieces of the final string efficiently. - For each character
chinorder:- If
chexists incounts:- Append
chrepeatedcounts[ch]times toout. - Remove
chfromcounts(so it won’t be added again later).
- Append
- If
- Append remaining characters (not in
order). For each(ch, cnt)still left incounts:- Append
chrepeatedcnttimes toout(Their relative order doesn’t matter.).
- Append
- Join all parts in
outinto one string and return it.
Take a look at the illustration below to understand the solution more clearly.
Solution implementation
Time complexity
The time complexity is O(n + m) where n is the length of s and m is the length of order. Counting characters in s takes linear time, and building the output touches each character count a constant number of times overall.
Space complexity
The space complexity is O(1) in terms of alphabet size because the frequency map stores at most 26 lowercase letters. The output itself requires O(n) space to build the permuted string.
Edge cases
scontains no characters fromorder- Example:
order = "abc",s = "ddd" - Why the solution handles it: the ordered loop appends nothing, and all characters remain in the leftover map and get appended normally.
- Example:
orderincludes characters not present ins- Example:
order = "xyz",s = "aabb" - Why the solution handles it: missing characters simply don’t appear in the frequency map and are skipped.
- Example:
shas many duplicates of ordered characters- Example:
order = "cba",s = "aaabbbccccd" - Why the solution handles it: counts ensure each ordered character group is emitted fully and in the correct group order.
- Example:
- Smallest inputs
- Example:
order = "a",s = "a" - Why the solution handles it: counts are correct and the loops still produce the right result.
- Example:
Common pitfalls
- Trying to “sort” with a comparator without defining how to rank characters not in
order- This often leads to bugs or inconsistent placement of characters that don’t appear in
order.
- This often leads to bugs or inconsistent placement of characters that don’t appear in
- Forgetting about duplicates
- Placing each character once based on
orderand ignoring frequency will produce a string missing characters.
- Placing each character once based on
- Not removing processed characters from the count map
- This can accidentally output ordered characters twice: once in the
orderloop and again in leftovers.
- This can accidentally output ordered characters twice: once in the
- Assuming the remaining characters must keep their original order
- The problem allows any permutation; forcing stability can complicate your solution unnecessarily.