C算法-UT哈希+并查集

leetcode面试题 17.07. 婴儿名字。之前写过一篇根本不算HASH的HASH,现在借鉴了各位大神的UT哈希方法,把这个题目理一理。

思路如下:
1、通过info存取names的关键信息,本质就是比names多了cnt及root信息,用处是记录最终的cnt信息,以及给团队赋值为最小字典序(char *root)
2、通过hash存取names的关键信息,用处是支撑synonyms元素的快速查找对应索引位置HASH_FIND,将两个索引进行并查集处理

小知识点一:对字符串分割
names = [“John(15)”,“Jon(12)”,“Chris(13)”,“Kris(4)”,“Christopher(19)”]
synonyms = ["(Jon,John)","(John,Johnny)","(Chris,Kris)","(Chris,Christopher)"]
分割方法依次如下,其中对字符串的分割停止表达是:%[^ xxx], xxx就是想停止的字符

sscanf(names[i],"%[^(](%d)", info[i].name, &cnt);
sscanf(syn,"(%[^,],%[^)])", tmps[0], tmps[1]);

小知识点二:UT哈希方法
1、建立HASH

	hash_st *pool;
	hash_st *head;
    pool = (hash_st *)malloc(namesSize * sizeof(hash_st));
    head = NULL;

2、查找&添加
遗留为什么这里用的HASH_FIND,如下链接总结了UT哈希

        hash_st *new = &pool[psize];
        new->key = info[i].name;
        new->id = i;

        hash_st *tmph;
        HASH_FIND_STR(head, new->key, tmph);
        if(tmph == NULL) {
    
    
            HASH_ADD_KEYPTR(hh, head, new->key, tmplen, new);
            psize++;            
        }

3、查找具体索引

        hash_st *tmph;
        HASH_FIND_STR(head, tmps[j], tmph);
        if(tmph == NULL){
    
    
            find = false;
            break;
        }
        id[j] = tmph->id; 

完整代码如下:

#define STR_LEN  50

typedef struct _info_st
{
    
    
    char name[STR_LEN];
    char *root;
    int cnt;
}info_st;

typedef struct _hash_st
{
    
    
    char *key;
    int id;
    UT_hash_handle hh;
}hash_st;

info_st *info;
hash_st *pool;
hash_st *head;

void InitialFa(int *fa, int len)
{
    
    
    for(int i = 0; i < len; i++) {
    
    
        fa[i] = i;
    }
}
int FindFather(int *fa, int i) {
    
    
    if(fa[i] == i) {
    
    
        return i;
    }
    int son = i;
    while(fa[i] != i) {
    
    
        i = fa[i];
    }
    int tmp;
    while(fa[son] != son) {
    
    
        tmp = fa[son];
        fa[son] = i;
        son = tmp;
    }
    return i;
}
void Set(int* fa, int i, int j) {
    
    
    int xx = FindFather(fa, i);
    int yy = FindFather(fa, j);
    if (xx != yy) {
    
    
        fa[yy] = xx;
    }
}

void InitialInfoHash(char** names, int namesSize)
{
    
    
    int psize = 0;
    int i, cnt, tmplen;
    info = (info_st *)malloc(namesSize * sizeof(info_st));
    pool = (hash_st *)malloc(namesSize * sizeof(hash_st));
    head = NULL;
    for (i = 0; i < namesSize; i++) {
    
    
        sscanf(names[i],"%[^(](%d)", info[i].name, &cnt);
        tmplen = strlen(info[i].name);
        info[i].root = info[i].name;
        info[i].cnt = cnt; 
        hash_st *new = &pool[psize];
        new->key = info[i].name;
        new->id = i;

        hash_st *tmph;
        HASH_FIND_STR(head, new->key, tmph);
        if(tmph == NULL) {
    
    
            HASH_ADD_KEYPTR(hh, head, new->key, tmplen, new);
            psize++;            
        }
    }
}

void Conbine(int*fa, const char * syn)
{
    
    
    char tmps[2][STR_LEN];
    int id[2];
    bool find = true;
    int j;
    sscanf(syn,"(%[^,],%[^)])", tmps[0], tmps[1]);
    for (j = 0; j < 2; j++) {
    
    
        hash_st *tmph;
        HASH_FIND_STR(head, tmps[j], tmph);
        if(tmph == NULL){
    
    
            find = false;
            break;
        }
        id[j] = tmph->id;           
    }
    if (find != true) {
    
    
        return;
    }
    Set(fa, id[0], id[1]);
}

char** trulyMostPopular(char** names, int namesSize, char** synonyms, int synonymsSize, int* returnSize){
    
    
    InitialInfoHash(names, namesSize);

    int *fa = (int *)malloc(namesSize * sizeof(int));
    InitialFa(fa, namesSize);
    
    int i;
    for(int i = 0; i < synonymsSize; i++) {
    
    
        Conbine(fa, synonyms[i]);
    }
    
    int rsize = 0;
    for(int i = 0; i < namesSize; i++)
    {
    
    
        int ff = FindFather(fa, i);
        if(strcmp(info[i].name, info[ff].root) < 0){
    
    
            info[ff].root = info[i].name;
        }
        if(i == ff) {
    
    
            rsize++;
            continue;
        }
        info[ff].cnt += info[i].cnt;
    }    
    char **ret = (char **)malloc(rsize * sizeof(char *));
    rsize = 0;
    for(i = 0; i < namesSize; i++) {
    
    
        if(i == FindFather(fa, i)){
    
    
            ret[rsize] = malloc((sizeof(info[i].root) + 10) * sizeof(char));
            sprintf(ret[rsize], "%s(%d)", info[i].root, info[i].cnt);
            rsize++;
        }
    }
    *returnSize = rsize;
    return ret;
}

猜你喜欢

转载自blog.csdn.net/weixin_45554139/article/details/106498029
今日推荐