【算法系列-哈希表】有效的字母异位词

【算法系列-哈希表】有效的字母异位词

欢迎来到【算法系列 】第三弹 🏆 哈希表 ,接下来我们将围绕哈希表这类型的算法题进行解析与练习!一起加油吧!!( •̀ ω •́ )✧✨

文章目录

  • 【算法系列-哈希表】有效的字母异位词
    • [1. 有效的字母异位词(LeetCode 242)](#1. 有效的字母异位词(LeetCode 242))
      • [1.1 思路分析🎯](#1.1 思路分析🎯)
      • [1.2 解题过程🎬](#1.2 解题过程🎬)
      • [1.3 代码示例🌰](#1.3 代码示例🌰)
    • [2. 赎金信(LeetCode 383)](#2. 赎金信(LeetCode 383))
      • [2.1 思路分析🎯](#2.1 思路分析🎯)
      • [2.2 代码示例🌰](#2.2 代码示例🌰)
    • [3. 字母异位分词(LeetCode 49)](#3. 字母异位分词(LeetCode 49))
      • [3.1 思路分析🎯](#3.1 思路分析🎯)
      • [3.2 解题过程🎬](#3.2 解题过程🎬)
      • [3.3 代码示例🌰](#3.3 代码示例🌰)
    • [4. 找到字符串中所有的字母异位词(LeetCode 438)](#4. 找到字符串中所有的字母异位词(LeetCode 438))
      • [4.1 思路分析🎯](#4.1 思路分析🎯)
      • [4.2 解题过程🎬](#4.2 解题过程🎬)
      • [4.3 代码示例🌰](#4.3 代码示例🌰)

1. 有效的字母异位词(LeetCode 242)

【题目链接】 有效的字母异位词 LeetCode 242

1.1 思路分析🎯

构建哈希表来解决问题

定义一个数组,数组长度为26,对应26个字母 这个数组的索引下标 由 字符串中的字符 - 'a' 转化而来('a'的ASCII码值为97),数组元素代表着这个字母在字符串中的词频

1.2 解题过程🎬

对 s 字符串进行遍历,每遍历到 s 字符串中的新字符,数组对应位置下的元素值 + 1;

对 t 字符串进行遍历,每遍历到 t 字符串中的新字符,数组对应位置下的元素值 - 1;

对数组进行遍历,若遍历到的数组元素 不等于 0,表示s字符串与t字符串之间存在数量不等的字母,返回false ;

上述循环结束,则返回true

1.3 代码示例🌰

java 复制代码
class Solution {
    public boolean isAnagram(String s, String t) {
        int[] arr = new int[26];
        for (int i = 0;i < s.length();i++) {
            arr[s.charAt(i) - 'a']++;
        }
        for (int i = 0;i < t.length();i++) {
            arr[t.charAt(i) - 'a']--;
        }
        for (int i = 0;i < arr.length;i++) {
            if (arr[i] != 0) {
                return false;
            }
        }
        return true;
    }
}

掌握了解题思路后,提供以下几道类型相似的题用来练习

2. 赎金信(LeetCode 383)

【题目链接】 赎金信 LeetCode 383

2.1 思路分析🎯

思路与上一题相同,只是最后在判断的时候需要排除掉词频小于0的情况(因为magazine中可能存在ransomNote没有的字符)

2.2 代码示例🌰

java 复制代码
class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        
        int[] arr = new int[26];

        for (int i = 0;i < ransomNote.length();i++) {
            arr[ransomNote.charAt(i) - 'a']++;
        }
        for (int i = 0;i < magazine.length();i++) {
            arr[magazine.charAt(i) - 'a']--;
        }
        for (int i = 0;i < arr.length;i++) {
            if (arr[i] > 0) {
                return false;
            }
        }
        return true;
    }
}

3. 字母异位分词(LeetCode 49)

【题目链接】字母异位分词 LeetCode 49

3.1 思路分析🎯

通过哈希表进行归类判断,将构成异位分词的字符串给放到同一个集合类中

3.2 解题过程🎬

当集合 list不为空时, 进入循环:

定义集合retArr用来存储构成异位分词的字符串,每次遍历完list集合后,将已经进入retArr中的字符串从 list 中删除

3.3 代码示例🌰

java 复制代码
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        List<String> list = new ArrayList<>();
        for (int i = 0;i < strs.length;i++) {
            list.add(strs[i]);
        }
        List<List<String>> ret = new ArrayList<>();
        while (!list.isEmpty()) {
            List<String> retArr = new ArrayList<>();
            String str1 = list.get(0);
            retArr.add(str1);
            for (int i = 1;i < list.size();i++) {
                String str2 = list.get(i);
                if (str1.length() == str2.length() && judge(str1, str2)) {
                    retArr.add(list.get(i));
                }
            }
            for (int j = 0;j < retArr.size();j++) {
                list.remove(retArr.get(j));
            }
            ret.add(retArr);
        } 
        return ret;
    }

    public boolean judge(String s1, String s2) {

        int[] arr = new int[26];
        for (int i = 0;i < s1.length();i++) {
            arr[s1.charAt(i) - 'a']++;
        }
        for (int i = 0;i < s2.length();i++) {
            arr[s2.charAt(i) - 'a']--;
        }
        for (int i = 0;i < arr.length;i++) {
            if (arr[i] != 0) {
                return false;
            }
        }
        return true;
    }
}

4. 找到字符串中所有的字母异位词(LeetCode 438)

【题目链接】找到字符串中所有的字母异位词 LeetCode 438

4.1 思路分析🎯

通过 滑动窗口 + 哈希表 解决问题

这道题判断字符串间是否构成异位词,对此可以通过记录词频来判断,即只关注字符数量而不关心字符顺序

4.2 解题过程🎬

定义两个数组:

sArr:用来记录 s 字符串中每个字母的词频,滑动窗口就在这个数组上进行移动;

tArr:用来记录 t 字符串中每个字母的词频,并作为窗口集合与t字符串是否构成异位词的标准;

初始化先进行一轮窗口判断,之后通过在sArr数组上进行窗口移动来判断窗口集合是否与t字符串构成异位词

4.3 代码示例🌰

java 复制代码
class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        
        List<Integer> ret = new ArrayList<>();
        int sLen = s.length();
        int pLen = p.length();
        if (sLen < pLen) { // 当 s 的长度小于 p的长度时,直接返回空数组即可
            return new ArrayList<>();
        } 

        int[] sArr = new int[26]; // sArr 用来记录 s 字符串中每个字母的词频
        int[] pArr = new int[26]; // tArr 用来记录 t 字符串中每个字母的词频

        for (int i = 0;i < pLen;i++) {
            sArr[s.charAt(i) - 'a']++; // 这里记录s字符串前 plen个(t字符串的长度) 长度的字符的词频
            pArr[p.charAt(i) - 'a']++; // 这里记录t字符串所有字符的词频,记录一次即可,后面作为判断标准
        }

        // 这里相当于第一次进行滑动窗口的判断,窗口第一次进入数组
        if (Arrays.equals(sArr, pArr)) {
            ret.add(0);
        }

        // 到这里滑动窗口已经进行过一轮判断了
        for (int i = 0;i < sLen - pLen;i++) {

            sArr[s.charAt(i) - 'a']--; // 窗口起始位置向后移动
            sArr[s.charAt(i + pLen) - 'a']++; // 窗口终止位置向后移动

            // 判断移动后的窗口集合是否与t字符串构成异位词
            if (Arrays.equals(sArr, pArr)) {
                ret.add(i + 1); // 之所以是 i + 1 而非 i 是因为在进入循环前已经对第一次窗口判断进行赋值了
            }
        }
        return ret;
    }
}

以上便是对有效的字母异位词类型题的介绍了!!后续还会继续分享其它算法系列内容,如果这些内容对大家有帮助的话请给一个三连关注吧💕( •̀ ω •́ )✧( •̀ ω •́ )✧✨

相关推荐
烦躁的大鼻嘎7 分钟前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode
C++忠实粉丝24 分钟前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
用户37791362947551 小时前
【循环神经网络】只会Python,也能让AI写出周杰伦风格的歌词
人工智能·算法
福大大架构师每日一题1 小时前
文心一言 VS 讯飞星火 VS chatgpt (396)-- 算法导论25.2 1题
算法·文心一言
EterNity_TiMe_1 小时前
【论文复现】(CLIP)文本也能和图像配对
python·学习·算法·性能优化·数据分析·clip
机器学习之心1 小时前
一区北方苍鹰算法优化+创新改进Transformer!NGO-Transformer-LSTM多变量回归预测
算法·lstm·transformer·北方苍鹰算法优化·多变量回归预测·ngo-transformer
yyt_cdeyyds2 小时前
FIFO和LRU算法实现操作系统中主存管理
算法
daiyang123...2 小时前
测试岗位应该学什么
数据结构
alphaTao2 小时前
LeetCode 每日一题 2024/11/18-2024/11/24
算法·leetcode
kitesxian2 小时前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode