Custom Sort String

Custom Sort String looks odd the first time you read it. You do not sort by A to Z. You sort by a rule that someone else gives you. So the interviewer wants to see if you can follow a custom order instead of the normal one. That small twist trips up a lot of people.

🎯 The Problem

You get two strings and you rearrange the second to match the order set by the first.

  • You get a string called order. It lists letters in the exact order you must follow.
  • You get a string called s. You rearrange its letters to match order.
  • A letter in s that is not in order can go anywhere. We place it at the end.
  • We call this a priority order, because each letter’s place comes from the order string.

For order = "cba" and s = "abcd": c comes first, then b, then a. The letter d is not in order, so it goes last. The answer is "cbad".

Input: order = "cba", s = "abcd"
Output: "cbad"
Explanation: c, b, a follow the order string. d is not listed, so it goes last.

Here is the rule drawn out. Each letter in s looks up its place in order.

order = cba

c gets priority 0

b gets priority 1

a gets priority 2

letters not in order

go to the end

🐒 Approach 1: Sort With a Comparator (Brute Force)

Sort the letters of s, but by their place in order instead of A to Z.

The idea:

  • Give the sort a comparator. That is the rule the sort uses to decide which letter comes first.
  • The rule: a letter’s position in order is its rank.
  • A letter not in order gets a large rank, so it lands at the end.

How it works:

  • For every pair of letters, look up both ranks in order.
  • The smaller rank comes first.

Why it is weak:

  • A sort compares letters again and again.
  • Every compare does a lookup in order.
  • Time grows as O(n log n), where n is the length of s.

Here is the comparator-style code for that idea:

custom_sort_string_comparator.py
def custom_sort_string(order, s):
rank = {ch: i for i, ch in enumerate(order)}
return "".join(sorted(s, key=lambda ch: rank.get(ch, len(order))))

⚑ Approach 2: Counting Sort (Best)

The idea in one line: we never compare letters, we just count them and rebuild.

The idea:

  • We only need how many times each letter appears in s.
  • Then we walk order and add each letter that many times.
  • This is a counting sort. It builds the answer from counts, not compares.

How it works:

  • Count every letter in s into a small table of 26 slots.
  • Walk order one letter at a time. Add each letter as many times as its count.
  • Add the leftovers last. Those are letters in s that were never in order.

Why it is fast:

  • No comparisons at all. We only read counts.
  • One pass to count, one pass to build. So O(n) time.

Here is a dry run of the counting approach on the example.

count s = abcd

a:1 b:1 c:1 d:1

walk order cba

add c once -> c

add b once -> cb

add a once -> cba

add leftover d -> cbad

Steps to Solve

  1. Count how many times each letter appears in s. Store the counts in a small table.
  2. Create an empty result.
  3. Walk through order one letter at a time.
  4. For each letter in order, add it to the result that many times, then set its count to zero.
  5. After order is done, walk through the table again and add any letter that still has a count left.
  6. Join everything into the final string and return it.

This Python version uses a Counter, which is a ready-made tool that counts how many times each letter appears.

custom_sort_string.py
from collections import Counter
def custom_sort(order, s):
count = Counter(s) # number -> count of each letter in s
result = []
for ch in order: # follow the custom order
result.append(ch * count[ch]) # add ch that many times
count[ch] = 0 # mark it as used
for ch, c in count.items(): # add leftover letters
result.append(ch * c)
return "".join(result)
print(custom_sort("cba", "abcd"))

The output of the above code will be:

cbad

Let us walk through the Python version line by line, because it shows the idea most clearly.

count = Counter(s) builds a table of how many times each letter shows up in s. For "abcd" every letter has a count of one. We start here because counting once lets us skip all the comparing later.

for ch in order: walks through the order string. This is what makes the sort custom. We do not go A to Z. We go in the exact order the problem gave us.

result.append(ch * count[ch]) adds that letter as many times as it appeared. In Python ch * 2 gives "cc". So if a letter appeared twice, we add two copies in one move.

count[ch] = 0 marks the letter as done. This matters. It stops us from adding the same letter again in the leftover step.

for ch, c in count.items(): handles the leftovers. These are letters that were in s but never in order, like d. They still have a count, so we add them now. They land at the end, which is exactly the rule.

return "".join(result) glues all the pieces into one final string. We built a list first and joined at the end because joining once is faster than adding to a string over and over.

⏱️ Time and Space Complexity

The comparator sort is fine but it compares letters again and again, so it costs O(n log n) time. The counting sort skips all comparisons. It counts once, then reads the counts, so it runs in O(n) time. Both need a small fixed table of 26 counts, so the extra space is tiny. That makes counting the clear winner, since it drops the time to O(n) for almost no extra cost.

Approach Time Complexity Space Complexity
Sort with custom comparator O(n log n) O(n)
Counting sort O(n) O(1) for the 26-letter table

Tip

In an interview, say the comparator-sort idea first. It shows you understand the order rule. Then explain how counting removes the sort completely and gets you to O(n). That jump is what they want to see.

🧩 Key Takeaways

  • βœ… You sort by a custom order, not by A to Z. Each letter’s place comes from the order string.
  • βœ… Counting how many times each letter appears lets you skip all the comparing.
  • βœ… Walk through order and add each letter as many times as its count.
  • βœ… Letters not in order still appear in the answer. Add them at the end.
  • βœ… Counting sort runs in O(n) time, faster than the O(n log n) comparator sort.

Check Your Knowledge

4 questions Show quiz Hide quiz

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What decides the order of letters in the answer?

    Why: You arrange the letters of s to match the custom order given by the order string.

  2. 2

    What happens to letters in s that are not in the order string?

    Why: Letters not listed in order can go anywhere, and the common rule is to put them at the end.

  3. 3

    Why is counting sort faster than the comparator sort here?

    Why: Counting sort tallies each letter once and reads the counts, so it skips the O(n log n) comparisons.

  4. 4

    What is the time complexity of the counting sort approach?

    Why: Counting each letter and reading the counts both take linear time, so the total is O(n).

πŸš€ What’s Next?