zoukankan      html  css  js  c++  java
  • 【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] != ''; 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]
    ", 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;
    }
  • 相关阅读:
    异常处理基本语法
    数字取舍(trunc round ceil floor)
    关于union的理解
    SQL Loader 导入EXCEL 数据到ORACLE 数据库
    临时表的使用方法
    对外投资
    存货盘盈盘亏核算
    现金流量表补充资料的编制公式
    会计科目的具体定义
    中英文职位对照之 会计与财务
  • 原文地址:https://www.cnblogs.com/ganxiang/p/14116529.html
Copyright © 2011-2022 走看看