PU Group Shifted Strings

Jan 01, 1970

Given a string, we can "shift" each of its letter to its successive letter, for example: "abc" -> "bcd". We can keep "shifting" which forms the sequence:

  • "abc" -> "bcd" -> ... -> "xyz"

Given a list of strings which contains only lowercase alphabets, group all strings that belong to the same shifting sequence.

Example:

  • Given: ["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"],
  • A solution is: [ ["abc","bcd","xyz"], ["az","ba"], ["acef"], ["a","z"] ]

C Solution:

struct He {
    int width;
    char *str;
    int returnInd;
    struct He *next;
};

struct Ht {
    int size;
    struct He **list;
};

void find_or_insert(struct Ht *ht, char ****res, int *size, int **columnSizes, int *returnSize, char *str) {
    int width;
    unsigned ind = 0, t = 1;
    for (width = 1; str[width]; width++) {
        int tmp = str[width] - str[width - 1];
        if (tmp < 0) tmp += 26;
        ind += tmp * t;
        t *= 10;
    }
    ind = ind % ht->size;
    struct He *p = ht->list[ind];
    while (p) {
        if (p->width == width) {
            int tmp = str[0] - p->str[0];
            tmp = tmp < 0 ? tmp + 26 : tmp;
            int j;
            for (j = 1; j < width; j++) {
                int dis = str[j] - p->str[j];
                dis = dis < 0 ? dis + 26 : dis;
                if (dis != tmp) break;
            }
            if (j == width) {
                (*columnSizes)[p->returnInd]++;
                (*res)[p->returnInd] = realloc((*res)[p->returnInd], (*columnSizes)[p->returnInd] * sizeof(char *));
                (*res)[p->returnInd][(*columnSizes)[p->returnInd] - 1] = malloc(width + 1);
                memcpy((*res)[p->returnInd][(*columnSizes)[p->returnInd] - 1], str, width + 1);
                return;
            }
        }
        p = p->next;
    }
    p = malloc(sizeof(struct He));
    p->str = str;
    p->width = width;
    if (*size == *returnSize) {
        *size += 1000;
        *res = realloc(*res, *size * sizeof(char **));
        *columnSizes = realloc(*columnSizes, *size * sizeof(int));
    }
    (*res)[*returnSize] = malloc(sizeof(char *));
    (*res)[*returnSize][0] = malloc(width + 1);
    memcpy((*res)[*returnSize][0], str, width + 1);
    (*columnSizes)[*returnSize] = 1;
    p->returnInd = *returnSize;
    ++*returnSize;
    p->next = ht->list[ind];
    ht->list[ind] = p;
}

char*** groupStrings(char** strings, int stringsSize, int** columnSizes, int* returnSize) {
    int size = 1000;
    *columnSizes = malloc(size * sizeof(int));
    char ***res = malloc(size * sizeof(char **));
    *returnSize = 0;
    struct Ht tmp, *ht = &tmp;
    ht->size = 1000;
    ht->list = malloc(ht->size * sizeof(struct He *));
    int i;
    for (i = 0; i < stringsSize; i++) {
        find_or_insert(ht, &res, &size, columnSizes, returnSize, strings[i]);
    }
    return res;
}

Summary:

  1. The logic behind is simple, but the code is troublesome.
  2. First, we need the hash function.
  3. Second, merge HashTable with the res.
  4. 0ms, 0%.

LeetCode: 249. Group Shifted Strings