【leetcode】49. 字母异位词分组

 

//1,使用质数解决哈希表关键字的问题,26个字母对应26个质数,不同字母组合的乘积肯定不同
//2,创建一个大小为 hashSize 的二维指针作为数组,
//3,使用所有字符串的 key % hashSize 分配到数组不同的位置对应的链表中
//4,每个二维数组中元素是一个链表,链表的元素是 字符串 key, 字符串位置 pos, 下一个指针 pNext 组成
//5,将每个链表中的元素按照 key 分配,字母异位词组合 具有相同的 key 肯定在同一个链表中

//学习点
//1,质数的运用,
//2,哈希表加二维链表的运用,数据结构的定义,哈希表初始化,元素插入,最后空间释放
//3,double类型的使用,浮点型求余系统函数 fmod,  float 类型数据求余 fmodf

#define     HASH_SIZE       199
#define     MAX_COL_SIZE    200         //相同 字母异位词的最大个数

//二维哈希链表元素定义
struct Hash_Node {
    double              key;
    int                 value;
    struct Hash_Node*   pNext;
};

//哈希表定义
struct Hash_Table {
    struct Hash_Node**  pHashHead;
    int                 iHashSize;
};

//函数一:哈希表初始化
bool hashTableInit(struct Hash_Table** pHashTable) {
    *pHashTable = (struct Hash_Table*)malloc(sizeof(struct Hash_Table));
    if (NULL == *pHashTable) return false;

    (*pHashTable)->iHashSize = HASH_SIZE;
    (*pHashTable)->pHashHead = (struct Hash_Node**)calloc(sizeof(struct Hash_Node*) , HASH_SIZE);

    if (NULL == (*pHashTable)->pHashHead) return false;

    return true;
}

//函数二:哈希表元素插入
bool hashTableInsert(struct Hash_Table* pHashTable, double key, int value){
    int     iTablePos       = 0;
    struct Hash_Node* pNode = NULL;

    //双精度浮点数求余的系统函数 fmod
    iTablePos = (int)fmod(key,  (double)HASH_SIZE);

    if (NULL == pHashTable->pHashHead[iTablePos])
    {
        pNode = (struct Hash_Node*)malloc(sizeof(struct Hash_Node));
        pNode->key = key;
        pNode->value = value;
        pNode->pNext = NULL;
        pHashTable->pHashHead[iTablePos] = pNode;
    }
    else
    {
        pNode = pHashTable->pHashHead[iTablePos];
        while ((NULL != pNode) && (NULL != pNode->pNext))
        {
            pNode = pNode->pNext;
        }

        pNode->pNext = (struct Hash_Node*)malloc(sizeof(struct Hash_Node));
        pNode = pNode->pNext;
        pNode->key = key;
        pNode->value = value;
        pNode->pNext = NULL;
    }
    return true;
}

//函数三:将字符串数组插入哈希表中
bool pushStrsInHashTable(struct Hash_Table* pHashTable, char** strs, int strsSize){
    double      lKey    = 1;
    int         primeTable[26] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101};      //质数列表分别对应26个英文字母
                                //a,b,c,d,e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
    for (int i = 0; i < strsSize; i++)
    {
        lKey=1;
        //计算字符串的 key, 每个字符串所有字符相乘
        for(int j=0; strs[i][j] != '\0'; j++)
        {
            lKey *= (double)primeTable[strs[i][j] - 'a'];
        }
        hashTableInsert(pHashTable, lKey, i);
    }
    return true;
}

//函数四:利用哈希表将字符串数组中的字母异位词存入结果中
//哈希表中每一组链表中都可能保存了不同 key 的字符串,但是 字母异位词组合肯定在一个链表中
//运用双指针,pNode 外面循环,pNext 在链表后面找相同 key 值的字符串,找到之后避免pNode重复,拷贝后将 key=0
void groupAnagramsUseHash(char** strs, char*** pRet, struct Hash_Table* pHashTable, int* returnSize, int* pColumnSizes){
    int         i           = 0;
    int         iCurCol     = 0;
    double      lTmpKey     = 0;

    struct Hash_Node* pNode = NULL;
    struct Hash_Node* pNext = NULL;

    for (i = 0; i < HASH_SIZE; i++)
    {
        if (NULL != pHashTable->pHashHead[i])
        {
            pNode = pHashTable->pHashHead[i];
            pNext = pNode;

            while(pNode != NULL)
            {
                if (pNode->key == 0)
                {
                    pNode = pNode->pNext;
                    pNext = pNode;
                    continue;
                }

                if (lTmpKey != pNode->key)
                {
                    //发现一个新key则申请新的空间存结果
                    pRet[iCurCol] = (char**)calloc(sizeof(char*) , MAX_COL_SIZE);
                    iCurCol += 1;
                    lTmpKey = pNode->key;
                }

                while(pNext != NULL)
                {
                    //将链表后所有 key 值相同的 字符串拷贝到同一层结果中,为一串字母异位词
                    if (pNext->key == lTmpKey)
                    {
                        pRet[iCurCol - 1][pColumnSizes[iCurCol - 1]]=strs[pNext->value];
                        pColumnSizes[iCurCol - 1] += 1;
                        pNext->key = 0;
                    }
                    pNext = pNext->pNext;
                }

                pNode = pNode->pNext;
                pNext = pNode;
            }

        }
    }
    *returnSize = iCurCol;
    return;
}

//函数五:释放哈希表空间
void freeHashTable(struct Hash_Table* pHashTable){
    int     i       = 0;
    struct Hash_Node* pNode = NULL;
    struct Hash_Node* pNext = NULL;

    if (pHashTable->pHashHead != NULL)
    {
        for (i = 0; i < HASH_SIZE; i++)
        {
            pNode = pHashTable->pHashHead[i];

            while(pNode != NULL)
            {
                pNext = pNode->pNext;
                free(pNode);
                pNode = pNext;
            }
        }
        free(pHashTable->pHashHead);
    }
    return;
}

char *** groupAnagrams(char ** strs, int strsSize, int* returnSize, int** returnColumnSizes){
    int                    i           = 0;
    char***                pRet        = NULL;
    struct Hash_Table*     pHashTable  = NULL;
    struct Hash_Node* pNode = NULL;

    pRet = (char***)calloc(sizeof(char**) , strsSize);
    *returnColumnSizes = (int *)calloc(sizeof(int) , strsSize);


    //1,哈希表初始化
    hashTableInit(&pHashTable);

    //2,将字符串数字插入哈希表中
    pushStrsInHashTable(pHashTable, strs, strsSize);

/*
    for (i = 0; i < HASH_SIZE; i++)
    {
        pNode = pHashTable->pHashHead[i];

        while (NULL != pNode)
        {
            printf("[i=%d][key=%ld][val=%d][%s]\n", i, pNode->key, pNode->value, strs[pNode->value]);
            pNode = pNode->pNext;
        }
    }
*/
    //3,利用哈希表将字符串数组中的字母异位词存入结果中
    groupAnagramsUseHash(strs, pRet, pHashTable, returnSize, *returnColumnSizes);

    //4,释放哈希表空间
    freeHashTable(pHashTable);
    free(pHashTable);

    //5,返回
    return pRet;
}

 

posted @ 2020-12-10 18:15  温暖了寂寞  阅读(121)  评论(0编辑  收藏  举报