代码训练LeetCode(48)字母异位词分组
代码训练(48)字母异位词分组
Author: Once Day Date: 2025年10月25日
漫漫长路,才刚刚开始…
全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客
参考文章:
- 49. 字母异位词分组 - 力扣(LeetCode)
- 力扣 (LeetCode) 全球极客挚爱的技术成长平台
文章目录
- 代码训练(48)字母异位词分组
- 1. 原题
- 2. 分析
- 3. 代码实现
- 4. 总结
1. 原题
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
示例 1:
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]
解释:
- 在 strs 中没有字符串可以通过重新排列来形成
"bat"。- 字符串
"nat"和"tan"是字母异位词,因为它们可以重新排列以形成彼此。- 字符串
"ate","eat"和"tea"是字母异位词,因为它们可以重新排列以形成彼此。示例 2:
输入: strs = [“”]
输出: [[“”]]
示例 3:
输入: strs = [“a”]
输出: [[“a”]]
strs[i] 仅包含小写字母
2. 分析
这个题目要求我们将给定的字符串数组中所有的字母异位词组合到一起。字母异位词指的是由相同字母以不同顺序组成的单词,例如 “eat”, “tea”, 和 “ate”。我们的任务是将所有的字母异位词归为一组,并返回这些组。
解题思路:
为了解决这个问题,我们可以使用哈希表(也称为字典)来存储字母异位词的分组。具体步骤如下:
- 初始化一个哈希表:键是排序后的单词,值是原始单词的列表。
- 遍历字符串数组:对于每个字符串,将其字符排序,然后检查排序后的字符串是否已经作为键存在于哈希表中。
- 填充哈希表:如果存在,则将原始字符串添加到对应的列表中。如果不存在,创建一个新的列表。
- 输出结果:最后,我们将哈希表中的所有值(即所有分组的列表)输出。
分析步骤“:
- 遍历字符串数组:时间复杂度为 O(n),其中 n 是字符串数组的长度。
- 字符串排序:每个字符串排序的平均时间复杂度为 O(k log k),其中 k 是字符串的平均长度。
- 哈希表操作:平均时间复杂度为 O(1)。
整体时间复杂度为 O(n * k log k),空间复杂度为 O(n * k),因为我们需要存储所有字符串。
举例分析:
假设输入为 strs = ["eat", "tea", "tan", "ate", "nat", "bat"]:
- 对 “eat” 排序得到 “aet”,将 “eat” 添加到哈希表:
{"aet": ["eat"]}。 - 对 “tea” 排序也得到 “aet”,加入已有的列表:
{"aet": ["eat", "tea"]}。 - 以此类推,最终哈希表为
{"aet": ["eat", "tea", "ate"], "ant": ["tan", "nat"], "abt": ["bat"]}。 - 输出结果为列表的值:
[["eat", "tea", "ate"], ["tan", "nat"], ["bat"]]。
3. 代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STR_LEN 101
#define HASH_TABLE_SIZE 10000// 定义哈希表节点
typedef struct HashNode {char *key;char **group;int size;struct HashNode *next;
} HashNode;// 哈希表初始化
HashNode* hashTable[HASH_TABLE_SIZE];// 简单的字符串哈希函数
unsigned int hash(char *str) {unsigned int hash = 5381;while (*str) {hash = ((hash << 5) + hash) + (*str++);}return hash % HASH_TABLE_SIZE;
}// 向哈希表中插入键值对
void insert(char *key, char *str) {unsigned int index = hash(key);HashNode *node = hashTable[index];while (node) {if (strcmp(node->key, key) == 0) {node->group[node->size++] = str;return;}node = node->next;}HashNode *newNode = (HashNode *)malloc(sizeof(HashNode));newNode->key = strdup(key);newNode->group = (char **)malloc(sizeof(char *) * 100);newNode->group[0] = str;newNode->size = 1;newNode->next = hashTable[index];hashTable[index] = newNode;
}// 主函数
char *** groupAnagrams(char ** strs, int strsSize, int* returnSize, int** returnColumnSizes) {for (int i = 0; i < HASH_TABLE_SIZE; i++) hashTable[i] = NULL;for (int i = 0; i < strsSize; i++) {char *s = strs[i];char sorted[MAX_STR_LEN];strcpy(sorted, s);qsort(sorted, strlen(sorted), sizeof(char), (int (*)(const void *, const void *)) strcmp);insert(sorted, s);}char ***result = (char ***)malloc(sizeof(char **) * strsSize);*returnColumnSizes = (int *)malloc(sizeof(int) * strsSize);int count = 0;for (int i = 0; i < HASH_TABLE_SIZE; i++) {HashNode *node = hashTable[i];while (node) {result[count] = node->group;(*returnColumnSizes)[count] = node->size;count++;node = node->next;}}*returnSize = count;return result;
}// 测试代码
int main() {char *strs[] = {"eat", "tea", "tan", "ate", "nat", "bat"};int strsSize = 6;int returnSize;int *returnColumnSizes;char ***groups = groupAnagrams(strs, strsSize, &returnSize, &returnColumnSizes);for (int i = 0; i < returnSize; i++) {for (int j = 0; j < returnColumnSizes[i]; j++) {printf("%s ", groups[i][j]);}printf("\n");}return 0;
}
4. 总结
这个题目主要考察了哈希表和字符串处理的应用,通过实际编码练习,可以加深对数据结构如哈希表的理解和应用。要提升编程能力,可以多做类似的字符串处理和数据结构综合应用题目,同时关注算法的时间和空间效率。
