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

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

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

文章目录

  • 【算法系列-哈希表】有效的字母异位词
    • [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;
    }
}

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

相关推荐
Java与Android技术栈7 分钟前
图像编辑器 Monica 之 CV 常见算法的快速调参
算法
别NULL20 分钟前
机试题——最小矩阵宽度
c++·算法·矩阵
珊瑚里的鱼20 分钟前
【单链表算法实战】解锁数据结构核心谜题——环形链表
数据结构·学习·程序人生·算法·leetcode·链表·visual studio
无限码力24 分钟前
[矩阵扩散]
数据结构·算法·华为od·笔试真题·华为od e卷真题
gentle_ice25 分钟前
leetcode——矩阵置零(java)
java·算法·leetcode·矩阵
查理零世26 分钟前
保姆级讲解 python之zip()方法实现矩阵行列转置
python·算法·矩阵
zhbi981 小时前
测量校准原理
算法
时间很奇妙!1 小时前
decison tree 决策树
算法·决策树·机器学习
sysu632 小时前
95.不同的二叉搜索树Ⅱ python
开发语言·数据结构·python·算法·leetcode·面试·深度优先
红鲤鱼遇绿鲤鱼2 小时前
uva 1354 Mobile Computing
算法