You are given two strings order
and s
. All the characters of order
are unique and were sorted in some custom order previously.
Permute the characters of s
so that they match the order that order
was sorted. More specifically, if a character x
occurs before a character y
in order
, then x
should occur before y
in the permuted string.
Return any permutation of s
that satisfies this property.
Example 1:
Input: order = "cba", s = "abcd"
Output: "cbad"
Explanation: "a"
, "b"
, "c"
appear in order, so the order of "a"
, "b"
, "c"
should be "c"
, "b"
, and "a"
.
Since "d"
does not appear in order
, it can be at any position in the returned string. "dcba"
, "cdba"
, "cbda"
are also valid outputs.
Example 2:
Input: order = "bcafg", s = "abcd"
Output: "bcad"
Explanation: The characters "b"
, "c"
, and "a"
from order
dictate the order for the characters in s
. The character "d"
in s
does not appear in order
, so its position is flexible.
Following the order of appearance in order
, "b"
, "c"
, and "a"
from s
should be arranged as "b"
, "c"
, "a"
. "d"
can be placed at any position since it's not in order. The output "bcad"
correctly follows this rule. Other arrangements like "dbca"
or "bcda"
would also be valid, as long as "b"
, "c"
, "a"
maintain their order.
Constraints:
1 <= order.length <= 26
1 <= s.length <= 200
order
and s
consist of lowercase English letters.order
are unique.The problem asks to sort the characters of a string s
according to the order specified in another string order
. Characters in order
are unique. If a character x
precedes character y
in order
, then x
must precede y
in the sorted s
. Characters from s
not present in order
can be placed anywhere in the result.
Two main approaches are presented:
Approach 1: Sorting with a Custom Key
This approach leverages the built-in sorting functionality of the programming language. We create a dictionary/map to store the index of each character in order
. The get
method with a default value of 0 handles characters not present in order
. The sorting is then done using this index as the key, ensuring the desired order.
Approach 2: Counting and Concatenation
This approach is more efficient in terms of time complexity. We first count the occurrences of each character in s
. Then, we iterate through order
, adding the corresponding characters to the result string based on their counts. Finally, we add any remaining characters not in order
to the end of the string.
The code examples below demonstrate both approaches in several programming languages.
Python3
from collections import Counter
class Solution:
def customSortString(self, order: str, s: str) -> str:
d = {c: i for i, c in enumerate(order)} # Create a dictionary mapping characters to their indices in order
return ''.join(sorted(s, key=lambda x: d.get(x, 0))) # Sort s using the dictionary as a key; characters not in d get index 0
Java
import java.util.*;
import java.util.stream.Collectors;
class Solution {
public String customSortString(String order, String s) {
int[] d = new int[26]; //array to store indices
for (int i = 0; i < order.length(); ++i) {
d[order.charAt(i) - 'a'] = i; //Store indices
}
List<Character> cs = new ArrayList<>(); //Convert string to list for easier sorting
for (char c : s.toCharArray()) cs.add(c);
cs.sort((a, b) -> d[a - 'a'] - d[b - 'a']); // Sort using custom comparator based on indices
return cs.stream().map(String::valueOf).collect(Collectors.joining()); //Convert back to string
}
}
C++
#include <algorithm>
#include <string>
#include <vector>
class Solution {
public:
string customSortString(string order, string s) {
int d[26] = {0}; // Array to store indices
for (int i = 0; i < order.length(); ++i) d[order[i] - 'a'] = i; //Store indices
sort(s.begin(), s.end(), [&](char a, char b) { return d[a - 'a'] < d[b - 'a']; }); //Sort using lambda expression
return s;
}
};
(Other languages are similar; the core idea remains the same: create a mapping and use it as a sorting key.)
Python3
from collections import Counter
class Solution:
def customSortString(self, order: str, s: str) -> str:
cnt = Counter(s) # Count character occurrences
ans = []
for c in order:
ans.append(c * cnt[c]) # Add characters from order based on count
cnt[c] = 0 #Reset count to 0
for c, v in cnt.items(): # Add remaining characters
ans.append(c * v)
return ''.join(ans)
Java
class Solution {
public String customSortString(String order, String s) {
int[] cnt = new int[26]; // Array to store counts
for (char c : s.toCharArray()) ++cnt[c - 'a']; // Count character occurrences
StringBuilder ans = new StringBuilder();
for (char c : order.toCharArray()) { // Iterate through order
while (cnt[c - 'a']-- > 0) ans.append(c); //Append characters based on counts
}
for (int i = 0; i < 26; ++i) { // Append remaining characters
while (cnt[i]-- > 0) ans.append((char) ('a' + i));
}
return ans.toString();
}
}
(Other languages are similar; the core idea remains the same: count, then concatenate based on the order
string.)
Approach 1:
s
. This is dominated by the sorting operation.Approach 2:
order
and N is the length of s
. This is because we iterate through order
and s
once each.Approach 2 is generally more efficient due to its linear time complexity compared to the logarithmic time complexity of Approach 1. However, the difference might be negligible for small input sizes.