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

题目链接:https://leetcode-cn.com/problems/group-anagrams/

题目:给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]

说明

所有输入均为小写字母。
不考虑答案输出的顺序。

分析:与前两道题同样,本题采用C语言的uthash库,这一道题与36. 有效的数独和136. 只出现一次的数字的 区别在于key是字符串,因此我们对uthash的接口重新进行了封装,本次的封装的key可以是结构体,同样可以在前两道题使用,这样的封装更具有拓展性。本地还用到了字符串排序与拷贝接口。

重新封装的接口如下,我们将key和val都作为结构体类型便于扩展,print接口需要根据需求自行修改:

typedef struct {
	int a;
	char b[20];
} uthash_key_s;

typedef struct {
	int c;
	char d;
} uthash_val_s;

typedef struct {
	uthash_key_s key;
	uthash_val_s val;
	UT_hash_handle hh;
} uthash_map_s;

uthash_map_s* uthash_create(void)
{
	uthash_map_s *s = (uthash_map_s *)malloc(sizeof(uthash_map_s));
	s = NULL;
	return s;
}

void uthash_add(uthash_map_s **hash, uthash_key_s key, uthash_val_s val)
{
	uthash_map_s *s;

	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	if (s == NULL) {
		s = (uthash_map_s *)malloc(sizeof(*s));
		s->key = key;
		HASH_ADD(hh, *hash, key, sizeof(uthash_key_s), s);
	}
	s->val = val;
}

uthash_map_s* uthash_find(uthash_map_s **hash, uthash_key_s key)
{
	uthash_map_s *s;

	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	return s;
}

void uthash_delete(uthash_map_s **hash, uthash_key_s key)
{
	uthash_map_s *s;

	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	if (s != NULL) {
		HASH_DEL(*hash, s);
		free(s);
	}
}

void uthash_delete_all(uthash_map_s **hash)
{
	uthash_map_s *s, *tmp;

	HASH_ITER(hh, *hash, s, tmp) {
		HASH_DEL(*hash, s);
		free(s);
	}
}

void uthash_print(uthash_map_s **hash)
{
	uthash_map_s *s;

	for (s = *hash; s != NULL; s = (uthash_map_s *)(s->hh.next)) {
		printf("key %d: val %d\n", s->key.a, s->val.c); // 自行根据数据结构修改
	}
}

unsigned int uthash_get_count(uthash_map_s **hash)
{
	return HASH_COUNT(*hash);
}

void uthash_test(void)
{
	// create
	uthash_map_s *hash = uthash_create();

	// add
	uthash_key_s key;
	key.a = 1;
	strcpy(key.b, "aaa");
	uthash_val_s val;
	val.c = 10;
	val.d = 'h';
	uthash_add(&hash, key, val);
	uthash_print(&hash);
	printf("\n");
	key.a = 2;
	strcpy(key.b, "bbb");
	val.c = 11;
	val.d = 'j';
	uthash_add(&hash, key, val);
	uthash_print(&hash);
	printf("\n");

	// find
	uthash_key_s key2;
	key2.a = 1;
	strcpy(key2.b, "aaa");
	if (uthash_find(&hash, key2) != NULL) {
		printf("find key\n");
	}

	// count
	printf("hash map num:%d\n", uthash_get_count(&hash));

	// delete
	uthash_delete(&hash, key2);
	uthash_print(&hash);
	printf("\n");

	// delete all
	uthash_delete_all(&hash);
	printf("hash map num:%d\n", uthash_get_count(&hash));
}

对以上的通用结构再次改造,以适应本题:

#define CHAR_NUM 1000

typedef struct {
	char name[CHAR_NUM];
} uthash_key_s;

typedef struct {
	int index;
} uthash_val_s;

typedef struct {
	uthash_key_s key;
	uthash_val_s val;
	UT_hash_handle hh;
} uthash_map_s;

uthash_map_s* uthash_create(void)
{
	uthash_map_s *s = (uthash_map_s *)malloc(sizeof(uthash_map_s));
	s = NULL;
	return s;
}

void uthash_add(uthash_map_s **hash, uthash_key_s key, uthash_val_s val)
{
	uthash_map_s *s;
 
	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	if (s == NULL) {
		s = (uthash_map_s *)malloc(sizeof(*s));
		s->key = key;
		HASH_ADD(hh, *hash, key, sizeof(uthash_key_s), s);
	}
	s->val = val;
}

uthash_map_s* uthash_find(uthash_map_s **hash, uthash_key_s key)
{
	uthash_map_s *s;

	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	return s;
}

void uthash_delete(uthash_map_s **hash, uthash_key_s key)
{
	uthash_map_s *s;

	HASH_FIND(hh, *hash, &key, sizeof(uthash_key_s), s);
	if (s != NULL) {
		HASH_DEL(*hash, s);
		free(s);
	}
}

void uthash_delete_all(uthash_map_s **hash)
{
	uthash_map_s *s, *tmp;

	HASH_ITER(hh, *hash, s, tmp) {
		HASH_DEL(*hash, s);
		free(s);
	}
}

void uthash_print(uthash_map_s **hash)
{
	uthash_map_s *s;

	for (s = *hash; s != NULL; s = (uthash_map_s *)(s->hh.next)) {
		printf("key %s: val %d\n", s->key.name, s->val.index); // 自行根据数据结构修改
	}
}

unsigned int uthash_get_count(uthash_map_s **hash)
{
	return HASH_COUNT(*hash);
}

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int cmp(const char* a, const char* b)
{
    return *a - *b;
}

char *** groupAnagrams(char ** strs, int strsSize, int* returnSize, int** returnColumnSizes){
    if (strsSize <= 0 || strs == NULL) {

        return NULL;    
    }
   
    char ***res = (char***)malloc(sizeof(char**) * strsSize);
    for (int i = 0; i < strsSize; i++) {
        res[i] = (char**)malloc(sizeof(char*) * strsSize);
    }

    *returnSize = 0;
    *returnColumnSizes = (int*)malloc(sizeof(int*) * strsSize);
    memset(*returnColumnSizes, 0, sizeof(int*) * strsSize);
  
    uthash_map_s *hash = uthash_create();
    uthash_key_s key;
    uthash_val_s val;
    uthash_map_s *hash_tmp;
    val.index = 0;
    int row, col;
    for (int i = 0; i < strsSize; i++) {
        memset(key.name, 0, CHAR_NUM);
        strcpy(key.name, strs[i]);
        qsort(key.name, strlen(key.name), sizeof(char), cmp);
        
        hash_tmp = uthash_find(&hash, key);
        if(hash_tmp == NULL) {
            row = val.index;
            col = 0;
            uthash_add(&hash, key, val);
            val.index++;
        } else {
            row = hash_tmp->val.index;
            col = *(*returnColumnSizes + row);
        }
        res[row][col] = strs[i];
        *(*returnColumnSizes + row) += 1;
    }
    
    *returnSize = val.index;
    //uthash_print(&hash);
    uthash_delete_all(&hash);
    
    return res;
}

执行用时 :152 ms, 在所有 C 提交中击败了42.73%的用户

内存消耗 :269.1 MB, 在所有 C 提交中击败了13.79%的用户

你可能感兴趣的:(leetcode,哈希,字符串,leetcode)