1. 程式人生 > 其它 >LeetCode 791 自定義字串排序

LeetCode 791 自定義字串排序

思路一

根據字串S構建對映表,對映表用一個長度為26的陣列表示。下標為i的內容表示字元'a' + iS中出現的位置。比如S = "cba",則對映表如下所示。

g_orderMap[0] = 2;
g_orderMap[1] = 1;
g_orderMap[2] = 0;
...

隨後將字串T中所有在S中出現的字元移動到T的前面,不在S中出現的字元移動到T的後面。比如T = "defgabc",則移動後為T = "abcgfed"。注意這只是其中一種移動方法,題目對不在S中出現的字元的相對順序沒有做要求。所以T中所有不在S中出現的字元的順序可以不用理會。

最後呼叫qsortT的前半部分按照S

給定的順序排序即可。

static int g_orderMap[26];

static void BuildOrderMap(const char *s)
{
    int index = 0;

    memset(g_orderMap, -1, sizeof(int) * 26);
    while (*s != '\0') {
        g_orderMap[*s - 'a'] = index;
        ++index;
        ++s;
    }
}

// 將在order串中出現的字元移到字串前;未出現的移到字串後
static void DivideStr(char *result, int *endPos)
{
    int len = strlen(result);
    int left = 0;
    int right = len - 1;
    char *temp = NULL;
    int tempLen = sizeof(char) * len;

    temp = (char *)malloc(tempLen + 1);
    if (temp == NULL) { return; }
    memset(temp, 0, tempLen + 1);

    for (int i = 0; i < len; ++i) {
        if (g_orderMap[result[i] - 'a'] > -1) {
            temp[left++] = result[i];
        } else {
            temp[right--] = result[i];
        }
    }
    *endPos = left;
    memcpy(result, temp, tempLen + 1);

    free(temp);
}

static int cmp(const void *a, const void *b)
{
    const char *pa = (char *)a;
    const char *pb = (char *)b;
    int idxA = (int)(*pa - 'a');
    int idxB = (int)(*pb - 'a');

    return g_orderMap[idxA] - g_orderMap[idxB];
}

char *customSortString(char *s, char *t){
    char *result = NULL;
    int len = strlen(t);
    int endPos = 0;

    result = (char *)malloc(len + 1);
    if (result == NULL) { return NULL; }
    memset(result, 0, len + 1);
    memcpy(result, t, len);

    BuildOrderMap(s);
    DivideStr(result, &endPos);
    qsort(result, endPos, sizeof(char), cmp);

    return result;
}

思路二

看了一下題解,發現題解的思路更加巧妙。先統計T串中各個字元出現的次數,然後遍歷S串,根據S串中字元的順序逐個新增字元到結果字串中。

char *customSortString(char *S, char *T)
{
    int idx = 0;
    int count[26];
    int len = strlen(T);
    char *result = NULL;

    result = (char *)malloc(len + 1);
    if (result == NULL) { return NULL; }
    memset(result, 0, len + 1);

    memset(count, 0, sizeof(int) * 26);
    for (int i = 0; i < len; ++i) {
        count[T[i] - 'a']++;
    }

    while (*S != '\0') {
        while (count[*S - 'a'] > 0) {
            result[idx++] = *S;
            count[*S - 'a']--;
        }
        S++;
    }
    
    // 將不在S串中出現的字元新增到result的末尾
    for (int i = 0; i < 26; ++i) {
        while (count[i] > 0) {
            result[idx++] = (char)('a' + i);
            count[i]--;
        }
    }

    return result;
}