0
点赞
收藏
分享

微信扫一扫

《五月集训》第二日——字符串

徐一村 2022-05-02 阅读 43

前言

这是五月集训打卡的第二天,今日的训练内容是 字符串 由于有很多还没有学习到的东西,今天的题目很多是根据题解来写的,因此今天的题目主要是以分析源代码的形式。

解题报告

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;
}

题解,计划一个星期以后回来重刷

举报

相关推荐

0 条评论