Leetcode819--最常见的单词--Java实现

        该题为leetcode819,属于一道简单题,虽然题比较简单,但是用到的api对于大部分新手小伙伴来说不太熟悉,而且细节也不少,下面展示三个方法,性能是逐渐提升的。

具体实现思路:

1. 将 paragraph 截取为一个个单词   
2. 将单词加入 map 集合,单词本身作为 key,出现次数作为 value,避免禁用词加入
3. 在 map 集合中找到 value 最大的,返回它对应的 key 即可

实现1:

实现特点:

1.分割单词时用的是正则表达式,利用逆向思维 ,优点:代码简单   缺点:性能不高

2.利用stream流的api进行实现,优点:代码简洁【当然我这里的注释较多】 缺点:性能不高

public String mostCommonWord1(String paragraph, String[] banned) {//14ms
        //利用正则表达式--不管大小写,所以统一转换为小写字符
        String[] split = paragraph.toLowerCase().split("[^A-Za-z]+");
        Set<String> set = Set.of(banned);//1.9以上版本,直接用,把字符串数组转换为set集合--不能在循环内,否则影响效率
        HashMap<String, Integer> map = new HashMap<>();
        for (String key : split) {
//            Integer value = map.get(key);
//            if (value == null) {
//                value = 0;//为value设初值
//            }
//            map.put(key, value + 1);//计数
            //用更简洁的api来表示---map中以compute开头的方法
            if (!set.contains(key)) {//避免禁用词加入
                //接收两个参数:1.要放入的key     2.lambda表达式--会把当时的键值传进来
                map.compute(key, (k, v) -> v == null ? 1 : v + 1);
            }
        }
        //map.entrySet  键值的集合   将此集合转化为流,调用流中的max方法去找最大的entry  max接受一个参数-->比较器对象
        //调用现成的比较器:Map.Entry.comparingByValue()--->根据值进行比较,然后确定最大值

        Optional<Map.Entry<String, Integer>> optional = map.entrySet().stream().max(Map.Entry.comparingByValue());
        //返回的是一个optional对象----找到entry-->但是最终只要entry中的key
        //所以对optional进行map操作,  Map进行筛选,只要key部分,optional为可选,entry的存在性不确定,如果没entry返回null
        return optional.map(Map.Entry::getKey).orElse(null);
    }

实现2:

优化点:不用lambda,利用传统的方法,在map里找一个出现次数最多的entry

    public String mostCommonWord2(String paragraph, String[] banned) {//12ms
        //利用正则表达式--不管大小写,所以统一转换为小写字符
        String[] split = paragraph.toLowerCase().split("[^A-Za-z]+");
        Set<String> set = Set.of(banned);//1.9以上版本,直接用,把字符串数组转换为set集合--不能在循环内,否则影响效率
        HashMap<String, Integer> map = new HashMap<>();
        for (String key : split) {
            if (!set.contains(key)) {//避免禁用词加入
                //接收两个参数:1.要放入的key     2.lambda表达式--会把当时的键值传进来
                map.compute(key, (k, v) -> v == null ? 1 : v + 1);
            }
        }
        int max = 0;//先假定最大的value值为0
        String maxKey = null;
        for (Map.Entry<String, Integer> e : map.entrySet()) {
            Integer value = e.getValue();
            if (value > max) {
                max = value;
                maxKey = e.getKey();
            }
        }
        return maxKey;
    }

实现3:

优化点:截取单词的时候--不利用正则表达式【看起来简洁,但是效率较低】 自己拼接每一个单词

public String mostCommonWord(String paragraph, String[] banned) {//5ms
        //利用正则表达式--不管大小写,所以统一转换为小写字符
        Set<String> set = Set.of(banned);//1.9以上版本,直接用,把字符串数组转换为set集合--不能在循环内,否则影响效率
        HashMap<String, Integer> map = new HashMap<>();
        char[] chars = paragraph.toLowerCase().toCharArray();//拿到字符串的字符数组
        StringBuilder sb = new StringBuilder();
        for (char ch : chars) {
            if (ch >= 'a' && ch <= 'z') {
                //做字符串拼接,利用StringBuilder比用+效率更高
                sb.append(ch);
            } else {
                String key = sb.toString();
                if (!set.contains(key)) {
                    map.compute(key, (k, v) -> v == null ? 1 : v + 1);
                }
//                sb = new StringBuilder();//创建新对象,重新拼接
                sb.setLength(0);//把旧的内容清空,下次拼接的时候就从0索引开始重新拼接,不用一直创建,提高性能
            }
        }
        if (sb.length() > 0) {//确保不会丢单词--做好收尾工作
            String key = sb.toString();
            if (!set.contains(key)) {
                map.compute(key, (k, v) -> v == null ? 1 : v + 1);
            }
        }
        int max = 0;//先假定最大的value值为0
        String maxKey = null;
        for (Map.Entry<String, Integer> e : map.entrySet()) {
            Integer value = e.getValue();
            String key = e.getKey();
            if (!Objects.equals(key, "") && value > max) {//此时的key可能为""  key是字符串,所以用包装类型来比较
                max = value;
                maxKey = e.getKey();
            }
        }
        return maxKey;
    }

 测试代码:

当然这三个方法都是通过leetcode的,大家可以用leetcode的测试用例

    public static void main(String[] args) {
        E08Leetcode819 e08 = new E08Leetcode819();
        String key = e08.mostCommonWord("Bob. hIt, baLl", new String[]{"bob", "hit"});
//        String key = e08.mostCommonWord("Bob", new String[]{"hit"});
        System.out.println(key); // ball
    }

  • 31
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ray-国

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值