前言
这是五月集训打卡的第二天,今日的训练内容是 字符串 由于有很多还没有学习到的东西,今天的题目很多是根据题解来写的,因此今天的题目主要是以分析源代码的形式。
解题报告
1.力扣500
原题链接
https://leetcode-cn.com/problems/keyboard-row/
题目概述
源码剖析
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
char ** findWords(char ** words, int wordsSize, int* returnSize){
*returnSize = 0;//初始化返回的容量
if(words == NULL || wordsSize == 0){
return NULL;
}
// 26个大写字母对应的行号,如Q在第1行
// 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
int hash[26]= {2, 3, 3, 2, 1, 2, 2, 2, 1, 2, 2, 2, 3, 3, 1, 1, 1, 1, 2, 1, 1, 3, 1, 3, 1, 3};
char **result = (char **)calloc(wordsSize, sizeof(char *));
int i, j, len;
int num = 0;//字符所在行号
for(i = 0; i < wordsSize; i++){
len = strlen(words[i]);
if(len == 0) continue;
num = hash[toupper(words[i][0]) - 'A']; //第一个字符的行号
for(j = 1; j < len; j++){
if(num != hash[toupper(words[i][j]) - 'A']){
break;
}
}
if(j == len){//单词所有字符在一行
result[(*returnSize)++] = words[i];
}
}
return result;
}
首先初始化容量,排除一下特殊情况(没有元素的时候),随后用一个哈希表将每一行的元素都定义起来(也就是每一个字母在键盘上的行数)
接下来对每一个单词进行遍历,只要有一个字母不在同一行之中都会直接 break
,如果没有出现过break
的话,就将这个字符串填入返回数组中,并且容量加一。
2.力扣1160
原题链接
https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters/
题目概述
解题思路
使用哈希表来记录下所给的字母表中的每个字母分别有多少个,每出现一次就在其对应的位置的值加一,然后对所给的词汇遍历,一旦当某个字母出现次数大于哈希表中的对应字母的数字,则不符合要求,然后累加符合要求的词汇的长度的总和返回即可。
源码剖析
int countCharacters(char ** words, int wordsSize, char * chars){
int nums = strlen(chars);
if (wordsSize == 0 || nums == 0)
return 0; //词汇表或者字母表为0都不可
int max = 0, j = 0;
int map[26], count[26]; //hash表 与 计数数组
memset(map, 0, sizeof(map)); //hash表初始化
for (int c = 0; c < nums; c++) { //生成hash值,一个字母如果出现一次,计数就加一
map[chars[c] - 'a']++;
}
for (int i = 0; i < wordsSize; i++) {
int len = strlen(words[i]);
if (len > nums) continue; //单个word长度超过字母表长度,无效
memset(count, 0, sizeof(count)); //计数数组归零
for (j = 0; j < len; j++) {
if (map[words[i][j] - 'a'] <= count[words[i][j] - 'a']) break; //hash值为0 或 重复字母不足
count[words[i][j] - 'a']++; //计数+1,代表字母重复一次
}
if (j == len) max += len; //当上面循环有break存在时,无效
}
return max;
}
详细见解题思路与代码注释
3.力扣1047
原题链接
https://leetcode-cn.com/problems/remove-all-adjacent-duplicates-in-string/
题目概述
源码剖析
char * removeDuplicates(char * S){
int len = strlen(S);
char *ret = (char*)malloc(sizeof(char)*(len + 1)); //这边len+1是因为要多一个用来存储'\0'的位置
int retSize = 1;
ret[0] = S[0];
for(int i=1; i<len; i++){
if(retSize > 0 && ret[retSize-1] == S[i]){
retSize--;
}else{
ret[retSize++] = S[i];
}
}
ret[retSize] = '\0'; //最后一个位置存入结束符号'\0'
return ret;
}
这是题解,等学习完栈的知识之后就立刻回来重刷这道题。
4.力扣1935
原题链接
https://leetcode-cn.com/problems/maximum-number-of-words-you-can-type/
题目概述
源码剖析
int canBeTypedWords(char * text, char * brokenLetters){
int hash[26]={0,};
for(int i=0;i<strlen(brokenLetters);i++)
{
hash[brokenLetters[i]-'a']++;
}
int n=strlen(text),count=0,flag=0;
for(int i=0;i<n;i++)
{
if(text[i]==' '&&flag==0)
{
count++;
}
if(text[i]==' '&&flag==1)
{
flag=0;
}
if(text[i]!=' '&&hash[text[i]-'a']!=0)
{
flag=1;
}
if(i==n-1&&flag==0)
{
count++;
}
}
return count;
}
题解,计划一个星期以后回来重刷