GuilinDev

Lc0791

05 August 2008

791. Custom Sort String

自定义字符串排序

字符串S和 T 只包含小写字符。在S中,所有字符只会出现一次。

S 已经根据某种规则进行了排序。我们要根据S中的字符顺序对T进行排序。更具体地说,如果S中x在y之前出现,那么返回的字符串中x也应出现在y之前。

返回任意一种符合条件的字符串T。

示例:

输入: S = “cba”

T = “abcd”

输出: “cbad”

解释:

S中出现了字符 “a”, “b”, “c”, 所以 “a”, “b”, “c” 的顺序应该是 “c”, “b”, “a”. 由于 “d” 没有在S中出现, 它可以放在T的任意位置. “dcba”, “cdba”, “cbda” 都是合法的输出。

注意:

S的最大长度为26,其中没有重复的字符。

T的最大长度为200。

S和T只包含小写字符。

思路

首先找出在 T 中出现的所有的 S 的元素,并且将这些元素按照 S 中出现的相对顺序排序,然后把 T 中出现的但不在 S 中的元素添加到排好序的字符串中,就得到了我们想要的结果。

在将 T 中出现的但不在 S 中的元素添加到字符串时,无序关注顺序,因为这些元素并没有在 S 中出现,不需要满足排序关系。

算法

一种巧妙的实现方法是统计 T 中每个字符出现的次数,把结果存储在数组 count 中,count[char] 表示字符 char 出现的次数。然后把在 S 中出现的字符按照在 S 中的相对顺序排列,剩余字符添加到当前字符串的后面,最终排好序的字符串顺序为 S + (未在 S 中出现的字符)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution {
    public String customSortString(String S, String T) {
        // count[char] = the number of occurrences of 'char' in T.
        // This is offset so that count[0] = occurrences of 'a', etc.
        // 'count' represents the current state of characters
        // (with multiplicity) we need to write to our answer.
        int[] count = new int[26];
        for (char ch : T.toCharArray())
            count[ch - 'a']++;

        // result will be our final answer.  We use StringBuilder to join
        // the answer so that we more efficiently calculate a
        // concatenation of strings.
        StringBuilder result = new StringBuilder();

        // Write all characters that occur in S, in the order of S.
        for (char ch : S.toCharArray()) {
            for (int i = 0; i < count[ch - 'a']; ++i)
                result.append(ch);
            // Setting count[char] to zero to denote that we do
            // not need to write 'char' into our answer anymore.
            count[ch - 'a'] = 0;
        }

        // Write all remaining characters that don't occur in S.
        // That information is specified by 'count'.
        for (char c = 'a'; c <= 'z'; ++c) {
            // result.append(String.valueOf(c).repeat(Math.max(0, count[c - 'a'])));
            for (int i = 0; i < count[c - 'a']; ++i) {
                result.append(c);
            }
        }
        return result.toString();
    }
}

常规解法, 用PQ和HashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
    public String customSortString(String S, String T) {
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        for (int i = 0; i < S.length(); ++i) { // 记住order字符串中某字符最后出现的位置,这样确定先后
            map.put(S.charAt(i), i);
        }

        PriorityQueue<Character> pq = new PriorityQueue<>(Comparator.comparingInt(map::get));
        StringBuilder leftOutChars = new StringBuilder("");
        for (int i = 0; i < T.length(); ++i) {
            if (map.containsKey(T.charAt(i))) {
                pq.offer(T.charAt(i));
            } else {
                leftOutChars.append(T.charAt(i));
            }
        }

        StringBuilder newString = new StringBuilder("");
        while (!pq.isEmpty()) {
            newString.append(pq.poll());
        }
        String result = newString + leftOutChars.toString();
        return result;
    }
}