算法修炼之路——【字符串】Leetcode 819 最常见的单词

题目描述

给定一个段落(paragraph)和一个禁用单词列表(banned)。返回出现次数最多,同时不在禁用列表中的单词。

题目保证至少有一个词不在禁用列表中,而且答案不唯一。

禁用列表中的单词用小写字母表示,不含标点符号。段落中的单词不区分大小写。答案都是小写字母。

示例1:

输入: paragraph = “Bob hit a ball, the hit BALL flew far after it was hit.” , banned = [“hit”]
输出: “ball”
解释: “hit” 出现了3次,但它是一个禁用的单词,“ball"出现了2次(同时没有其他单词出现2次),所以它是段落里出现次数最多的,且不在禁用列表中的单词。注意,所有这些单词在段落里不区分大小写,标点符号需要忽略(即使是紧挨着单词也忽略,比如"ball,”),"hit"不是最终的答案,虽然它出现次数最多,但它在禁用单词列表中。

提示:

  1. 段落长度范围[1, 1000]
  2. 禁用单词个数[0, 100]
  3. 禁用单词长度[1, 10]
  4. 答案是唯一的,且都是小写字母(即使在paragraph里是大写的,即使是一些特定的名词,答案都是小写的。)
  5. paragraph只包含字母、空格和下列标点符号! ? ' , ;
  6. 不存在没有连字符或者带有连字符的单词;
  7. 单词里只包含字母,不会出现省略号或其他标点符号。

思路分析

题目难度为简单 ,这里需要对输入字符串进行预处理,这里进行了字符串转换以及按照空格划分单词;且为了满足banned,这里使用set数据结构进行缓存,以便判断是否是禁用单词;

简单思路就是,首先将输入paragraph进行基于正则化的处理:去除标点符号,这里包括, . ? ! ;,之后是借用String.toLowerCase().split(" ")进行小写字母转化并按照空格划分,提取单词; 其次,借用HashMap<String, Integer>统计相应字符单词的频次,并使用String res, int maxCounter随时更新数据;最后,返回res.

注意: 这里比较巧妙地利用了答案唯一 这个说明,即去除掉禁用单词,有且仅有一个最大频次值,故这里只是随着遍历更新频次值和频次最大值对应的字符串res即可。

解题代码

    public static String solution(String paragraph, String[] banned) {
        Map<String, Integer> map = new HashMap<>();
        Set<String> bannedSet = new HashSet<>();
        
        bannedSet.addAll(Arrays.asList(banned));
        String[] strArr = paragraph.replaceAll("[,.?!;]", "").toLowerCase().split(" ");
        
        int maxCounter = 0;
        String res = "";
        
        for(String s : strArr){
            if(!bannedSet.contains(s)){
                if(!map.containsKey(s))
                    map.put(s, 1);
                else
                    map.replace(s, map.get(s)+1);
                
                res = maxCounter > map.get(s) ? res : s;
                maxCounter = Math.max(maxCounter, map.get(s));
            }           
        }        
        return res;
    }

复杂度分析

这里我们设n, mparagraph, banned的长度:

时间复杂度: 这里我们对两个字符串均进行了一定的预处理,故时间复杂度为O(n + m);
空间复杂度: 我们分别将输入数据存放至辅助容器bannedSet , strArr中,故空间复杂度为O(n + m);

Github源码

完整可运行文件请访问GitHub

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值