Java&C++题解与拓展——leetcode819.最常见的单词【C++字符串转小写or大写】

121 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

每日一题做题记录,参考官方和三叶的题解

题目要求

image.png

思路:模拟

构建一个哈希表存单词和出现的次数,注意把禁用词直接排除掉不计入。

Java

class Solution {
    public String mostCommonWord(String paragraph, String[] banned) {
        Set<String> ban = new HashSet<>(); //禁用词
        for(String b : banned)
            ban.add(b);

        char[] cs = paragraph.toCharArray();
        int n = cs.length;
        String res = null;

        Map<String, Integer> map = new HashMap<>(); //记录单词与出现次数

        for(int i = 0; i < n; ) {
            if(!Character.isLetter(cs[i]) && ++i >= 0) //跳过空格标点等非字母元素
                continue;
            int j = i;
            while(j < n && Character.isLetter(cs[j])) //获取当前单词
                j++;
            String sub = paragraph.substring(i, j).toLowerCase(); //转小写
            i = j + 1;
            if(ban.contains(sub))
                continue;
            map.put(sub, map.getOrDefault(sub, 0) + 1); //计数加一
            if(res == null || map.get(sub) > map.get(res)) //更新答案
                res = sub;
        }
        return res;
    }
}
  • 时间复杂度:O(n+m)O(n+m),遍历paragraphparagraphnn位和bannedbannedmm位。
  • 空间复杂度:O(n+m)O(n+m),用来存禁用词的banban长度为mm,用来存单词计数的哈希表mapmap长度最大为nn,还有个paragrahparagrahtoCharArray长度为nn(可不用)。

C++

和Java区别不大,但有一个点(昨天也是)——C++的取子串两个参数分别是起始点和长度,而不是Java的起点和终点。

class Solution {
public:
    string mostCommonWord(string paragraph, vector<string>& banned) {
        int n = paragraph.size();
        string res = "";
        unordered_map<string, int> map; //记录单词与出现次数
        transform(paragraph.begin(), paragraph.end(), paragraph.begin(), ::tolower); //转小写

        for(int i = 0; i < n; ) {
            if(!isalpha(paragraph[i]) && ++i >= 0) //跳过空格标点等非字母元素
                continue;
            int j = i;
            while(j < n && isalpha(paragraph[j])) //获取当前单词
                j++;
            string sub = paragraph.substr(i, j - i);
            i = j + 1;
            if(count(banned.begin(), banned.end(), sub))
                continue;
            map[sub]++; //计数加一
            if(res == "" || map[sub] > map[res]) //更新答案
                res = sub;
        }
        return res;
    }
};
  • 时间复杂度:O(n+m)O(n+m),遍历paragraphparagraphnn位和bannedbannedmm位。
  • 空间复杂度:O(n+m)O(n+m),用来存禁用词的banban长度为mm,用来存单词计数的哈希表mapmap长度最大为nn

转小写/大写的几种方法

方法功能
tolower(c)单个字符cc转为小写
toupper(c)单个字符cc转为大写
strlwr(str)字符串strstr转为小写,返回指向strstr指针
strupr(str)字符串strstr转为大写,返回指向strstr指针
transform(begin, end, res, opration)将起始迭代器beginbegin和结尾迭代器endend中间的字符按oprationopration处命令进行转换,将结果存至resres,转大写为::toupper、转小写为::tolower

P.S.transform函数还有很多用法,在此不详述,可参考这里

总结

这一周似乎天天都在模拟,管他什么题直接模拟……感觉人都要变傻了。


欢迎指正与讨论!