关于hash表的一些练习题

1.前言

我在前文已经讲述了,HashTable的代码实现,这次来讲讲如何实现hash算法来写一些练习题吧

对于hash表存在的优点就是:快速搜索,高效插入和删除和快速搜索

2.习题练习

2.1返回不重复子串的最大长度

示例 1:

复制代码
输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子字符串是 "abc",所以其长度为 3。

示例 2:

复制代码
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子字符串是 "b",所以其长度为 1。

示例 3:

复制代码
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

示例 4:

复制代码
输入: s = ""
输出: 0
1.思路分析:

1.使用双指针实现,定义一个begin表示最大索引的起始位置,end记录结束位置

2.创建一个hash表键存数据,值存数据的索引

3.取出end下标的元素来判断hash表有没有,没有的话连同它的索引添加进去,如果遇到重复的调整begin为重复元素第一次出现的位置 + 1,然后重复元素的索引更新

4.在你end每走一次都取出substring(start,end + 1)这个就是每一个子串,获取出他们的最大长度即可

2.代码实现
java 复制代码
 public int lengthOfLongSubstring(String s) {
        HashMap<Character, Integer> map = new HashMap<>();
        int begin = 0;//记录起始位置
        int maxLength = 0;//最大长度
        for (int end = 0; end < s.length(); end++) {
            char ch = s.charAt(end);
            if (map.containsKey(ch)) {//重新调整begin
                //防止begin往后走(begin前面的元素与其重复不处理  )
                begin = Math.max(map.get(ch) + 1,begin);
            }
            //重复更新   不重复添加
            map.put(ch, end);
            maxLength = Math.max(maxLength, end - begin + 1);
        }
        return maxLength;
    }

2.2 出现单词次数最多的单词

注意本题的要求: 1 . 答案是唯一的 2.并且存在禁入词

1.思路分析

1.将大串进行切割成为多个单词

2.将单词添加到map集合中,本身是key,出现次数是value,并且避免禁用词加入

3.在map集合找到value最大的,返回它对应的key即可

4.在每次添加到hash表的时候,判断是否为禁用词,即可舍弃禁用词

2.代码实现

1.普通代码

java 复制代码
public String mostCommonWord(String s, String[] banned){
        String[] s1 = s.toLowerCase().split("[^a-zA-Z]+");//排除单词字符就是分隔符
        HashMap<String,Integer> map = new HashMap();

        //因为需要用到contains()方法所以需要转换为set集合
        Set<String> set = Arrays.stream(banned).collect(Collectors.toSet());
          for (String s2 : s1) {
                if (map.containsKey(s2)){
                    map.put(s2,1);
                }else {
                    Integer value = map.get(s2);
                    value++;
                    map.put(s2,value);
                }
            }
        Optional<Map.Entry<String, Integer>> max = map.entrySet().stream()
                .max(Map.Entry.comparingByValue());
        return max.map(Map.Entry::getKey).orElse(null);
        //这样也可以
 //            Integer value = map.get(s2);
//            if (value == null){
//                value = 0;
//            }
//            map.put(s2,value + 1);

2.stream流进行优化

java 复制代码
public String mostCommonWord(String s, String[] banned){
        String[] s1 = s.toLowerCase().split("[^a-zA-Z]+");//排除单词字符就是分隔符
        HashMap<String,Integer> map = new HashMap();

        //因为需要用到contains()方法所以需要转换为set集合
        Set<String> set = Arrays.stream(banned).collect(Collectors.toSet());
        for (String s2 : s1) {

//            //lambda表达式实现
            if (!set.contains(s2)) map.compute(s2, ( k, v ) -> v == null ? 1 : v + 1);
        }

        Optional<Map.Entry<String, Integer>> max = map.entrySet().stream()
                .max(Map.Entry.comparingByValue());
        return max.map(Map.Entry::getKey).orElse(null);

3.优化分析

stream流和正则表达式会时间复杂度高

这个实现不使用 Stream 流和正则表达式,而是逐个字符检查输入字符串 s 的每个字符。

一旦遇到非字母字符,我们将当前的单词(由连续的字母字符组成)检查是否在 bannedSet 中,

如果不在,则更新该单词的出现次数并比较是否为最常见的单词。

通过避免使用正则表达式的 split() 方法以及通过字符级别的处理,可以降低时间复杂度。

然而,这种实现方式可能会稍微增加代码的复杂性和可读性,因此在具体情况下需要根据实际需求进行权衡。

java 复制代码
 public String mostCommonWord2(String s, String[] banned) {
        s = s.toLowerCase();
        StringBuilder word = new StringBuilder();
        HashMap<String, Integer> map = new HashMap<>();

        Set<String> bannedSet = new HashSet<>(Arrays.asList(banned));

        int maxCount = 0;
        String mostCommonWord = "";

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (Character.isLetter(c)) {
                word.append(c);
                if (i != s.length() - 1) {
                    continue;
                }
            }

            if (word.length() > 0) {
                String currentWord = word.toString();
                if (!bannedSet.contains(currentWord)) {
                    int count = map.getOrDefault(currentWord, 0) + 1;
                    map.put(currentWord, count);
                    if (count > maxCount) {
                        maxCount = count;
                        mostCommonWord = currentWord;
                    }
                }
                word = new StringBuilder();//也可以不重新创建  用word.setLength(0)来清空
            }
        }

        return mostCommonWord;
    }
相关推荐
2301_764441334 小时前
LISA时空跃迁分析,地理时空分析
数据结构·python·算法
东北洗浴王子讲AI4 小时前
GPT-5.4辅助算法设计与优化:从理论到实践的系统方法
人工智能·gpt·算法·chatgpt
Billlly5 小时前
ABC 453 个人题解
算法·题解·atcoder
玉树临风ives5 小时前
atcoder ABC 452 题解
数据结构·算法
feifeigo1235 小时前
基于马尔可夫随机场模型的SAR图像变化检测源码实现
算法
fengfuyao9856 小时前
基于STM32的4轴步进电机加减速控制工程源码(梯形加减速算法)
网络·stm32·算法
无敌昊哥战神7 小时前
深入理解 C 语言:巧妙利用“0地址”手写 offsetof 宏与内存对齐机制
c语言·数据结构·算法
小白菜又菜7 小时前
Leetcode 2075. Decode the Slanted Ciphertext
算法·leetcode·职场和发展
Proxy_ZZ07 小时前
用Matlab绘制BER曲线对比SPA与Min-Sum性能
人工智能·算法·机器学习
黎阳之光7 小时前
黎阳之光:以视频孪生领跑全球,赋能数字孪生水利智能监测新征程
大数据·人工智能·算法·安全·数字孪生