LeetCode刷题笔记(C语言)
Hash应用
题二、给你一个字符串数组 words ,请你找出所有在 words 的每个字符串中都出现的共用字符(包括重复字符),并以数组形式
返回。你可以按任意顺序返回答案。
- 1 <= words.length <= 100
- 1 <= words[i].length <= 100
- words[i] 由小写英文字母组成
方法一:使用哈希(Hash)进行查询统计出共用(及重复)的字符。
原因:使用此方法的原因是因为题目让我们找出每个字符串的共用字符,而字符串的字符本身的英文字母ANSI码就与数组下标有对应的线性关系,因此构成了一个哈希表(也就是以为数组),所以我们可以将每一个字符串建立对应的哈希表,也就是二位数组了,如下图所示。
上图对应的程序为:
18. /* 将每个字符串出现的字符个数统计到其对应的Hash表中 */
19. for(x = 0;x < wordsSize;x++) {
20. //printf("%s字符串字母个数%d\r\n",*(words),strlen(*(words+x)));
21. for(i = 0;i < strlen(*(words+x));i++) {
22. //printf("第%d个字符串,第%d个字母:%c\r\n",x,i,*((*(words+x))+i));
23. y = (int)(*((*(words+x))+i) - 'a'); //某个字符串对应的Hash表下标
24. HashMap[x][y] += 1; //统计出现的英文字母个数
25. }
26. }
通过哈希表方法统计出了每个字符串对应出现的字符个数,那么我们就需要对每个字符串中的每个字符个数就行两两比较,查找出所有字符串的共用字符(使用打擂台算法)。
上图对应的程序为:
27. /* 比较每个字符串某个字母的统计个数,找出统计出现的字母个数最少的值 */
28. for(y = 0;y < 26;y++) {
29. for(x = 0;x < wordsSize;x++) {
30. if(x == 0) min = HashMap[x][y];
31. else if(min > HashMap[x][y]) min = HashMap[x][y]; //获取对应字母的最小统计值
32. }
33. /* 当满足最小值大于零,说明,该字母在每个字符串都出现了,即为共用字符 */
34. // if(min > 0) {
35. // //printf("共用字母%c的个数:%d\r\n",(char)(y+(int)'a'),min);
36. // }
37. /* 将共用的字母以字符串方式统计到返回值变量中 */
38. for(i = 0;i < min;i++) {
39. rep_char[*returnSize] = malloc(sizeof(char)*2); //一个字母为字符串,那么为两个字节空间,例如"a" = 'a' + 0
40. rep_char[*returnSize][0] = y + 'a';
41. rep_char[*returnSize][1] = 0;
42. (*returnSize)++; //该字母重复字符个数累加
43. }
44.
45. }
通过上面两个步骤分解,基本就得出了题目想要实现的功能了。题目完整的程序如下:
1. /**
2. * Note: The returned array must be malloced, assume caller calls free().
3. */
4. /* words:字符串数组,wordsize:字符串输出的字符串个数,returnSize:重复字符的个数 */
5. char ** commonChars(char ** words, int wordsSize, int* returnSize){
6. /*
7. * x为字符串循环变量(下标)
8. * y为英文字母的循环变量(下标)
9. * i为每个字符串的字符循环变量
10. * min存储每个重复字母的个数
11. */
12. int x,y,i,min;
13. int HashMap[wordsSize][26]; //统计每个字符串对应下的每个英文字母出现的个数
14. char** rep_char = malloc(sizeof(char*) * 100); //用于保存共用字符(包括重复字符)
15. memset(HashMap,0,sizeof(HashMap)); //清空二维数组Hash表
16. x = y = i = *returnSize = 0; //初始化变量
17.
18. /* 将每个字符串出现的字符个数统计到其对应的Hash表中 */
19. for(x = 0;x < wordsSize;x++) {
20. //printf("%s字符串字母个数%d\r\n",*(words),strlen(*(words+x)));
21. for(i = 0;i < strlen(*(words+x));i++) {
22. //printf("第%d个字符串,第%d个字母:%c\r\n",x,i,*((*(words+x))+i));
23. y = (int)(*((*(words+x))+i) - 'a'); //某个字符串对应的Hash表下标
24. HashMap[x][y] += 1; //统计出现的英文字母个数
25. }
26. }
27. /* 比较每个字符串某个字母的统计个数,找出统计出现的字母个数最少的值 */
28. for(y = 0;y < 26;y++) {
29. for(x = 0;x < wordsSize;x++) {
30. if(x == 0) min = HashMap[x][y];
31. else if(min > HashMap[x][y]) min = HashMap[x][y]; //获取对应字母的最小统计值
32. }
33. /* 当满足最小值大于零,说明,该字母在每个字符串都出现了,即为共用字符 */
34. // if(min > 0) {
35. // //printf("共用字母%c的个数:%d\r\n",(char)(y+(int)'a'),min);
36. // }
37. /* 将共用的字母以字符串方式统计到返回值变量中 */
38. for(i = 0;i < min;i++) {
39. rep_char[*returnSize] = malloc(sizeof(char)*2); //一个字母为字符串,那么为两个字节空间,例如"a" = 'a' + 0
40. rep_char[*returnSize][0] = y + 'a';
41. rep_char[*returnSize][1] = 0;
42. (*returnSize)++; //该字母重复字符个数累加
43. }
44.
45. }
46. // printf("重复个数:%d, 重复字母:%s,%s,%s\r\n",*returnSize,ans[0],ans[1],ans[2]);
47. return rep_char; //共用字母字符串数组返回值
48. }