自定义字符串排序
描述
-
给定两个字符串 order 和 s 。order 的所有字母都是 唯一 的,并且以前按照一些自定义的顺序排序
-
对 s 的字符进行置换,使其与排序的 order 相匹配。更具体地说,如果在 order 中的字符 x 出现字符 y 之前,那么在排列后的字符串中, x 也应该出现在 y 之前
-
返回 满足这个性质的 s 的任意一种排列
示例 1:
输入: order = "cba", s = "abcd"
输出: "cbad"
解释:
“a”、“b”、“c"是按顺序出现的,所以"a”、“b”、“c"的顺序应该是"c”、“b”、“a”。
因为"d"不是按顺序出现的,所以它可以在返回的字符串中的任何位置。“dcba”、“cdba”、"cbda"也是有效的输出。
示例 2
输入: order = "cbafg", s = "abcd"
输出: "cbad"
解释:字符 “b”、“c” 和 “a” 规定了 s 中字符的顺序。s 中的字符 “d” 没有在 order 中出现,所以它的位置是弹性的。
按照出现的顺序,s 中的 “b”、“c”、“a” 应排列为"b"、“c”、“a”。“d” 可以放在任何位置,因为它没有按顺序排列。输出 “bcad” 遵循这一规则。其他排序如 “dbca” 或 “bcda” 也是有效的,只要维持 “b”、“c”、“a” 的顺序。
提示
- 1 <= order.length <= 26
- 1 <= s.length <= 200
- order 和 s 由小写英文字母组成
- order 中的所有字符都 不同
Typescript 版算法实现
1 ) 方案1:自定义排序
function customSortString(order: string, s: string): string {
// 创建一个数组来存储每个字符的优先级值
const val: number[] = new Array(26).fill(0);
// 根据 `order` 字符串设置每个字符的优先级值
for (let i = 0; i < order.length; ++i) {
const charCode = order[i].charCodeAt(0) - 'a'.charCodeAt(0);
val[charCode] = i + 1;
}
// 将字符串 `s` 转换为字符数组
const arr: string[] = Array.from(s);
// 按照 `val` 数组中的优先级对字符数组进行排序
arr.sort((c0, c1) => {
const index0 = c0.charCodeAt(0) - 'a'.charCodeAt(0);
const index1 = c1.charCodeAt(0) - 'a'.charCodeAt(0);
return val[index0] - val[index1];
});
// 将排序后的字符数组拼接成字符串并返回
return arr.join('');
}
2 ) 方案2:计数排序
function customSortString(order: string, s: string): string {
// 创建一个数组来存储每个字符的频率
const freq: number[] = new Array(26).fill(0);
// 统计字符串 `s` 中每个字符的出现次数
for (let i = 0; i < s.length; ++i) {
const ch: string = s[i];
freq[ch.charCodeAt(0) - 'a'.charCodeAt(0)]++;
}
let ans: string = '';
// 根据 `order` 字符串中的顺序构建结果字符串
for (let i = 0; i < order.length; ++i) {
const ch: string = order[i];
while (freq[ch.charCodeAt(0) - 'a'.charCodeAt(0)] > 0) {
ans += ch;
freq[ch.charCodeAt(0) - 'a'.charCodeAt(0)]--;
}
}
// 将剩余的字符(不在 `order` 中的字符)添加到结果字符串中
for (let i = 0; i < 26; ++i) {
while (freq[i] > 0) {
ans += String.fromCharCode(i + 'a'.charCodeAt(0));
freq[i]--;
}
}
return ans;
}