【哈希表专题】(1. 两数之和 面试题 01.02. 判定是否互为字符重排 217. 存在重复元素 219. 存在重复元素 II 49. 字母异位词分组)


哈希表

哈希表是什么:存储数据的容器

作用:快速查找某个元素。O(1)

当我们需要频繁的查找某一个数的时候,可以使用哈希表。

如何用哈希表

  1. 容器(哈希表)
  2. 用数组模拟简易哈希表
    (字符串中的“字符”)
    (数据范围很小的时候)

1. 两数之和

题目链接: leetcode1. 两数之和

在这里插入图片描述
解法一:暴力解法

  1. 先固定其中一个数
  2. 依次与该数之前的数相加

代码:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] ret = new int[2];
        for (int i = 0; i < nums.length; i++) {
            for (int j = i - 1; j >= 0; j--) {
                if (nums[i] + nums[j] == target) {
                    ret[0] = i;
                    ret[1] = j;
                    return ret;
                }
            }
        }
        return ret;
    }
}

twoSum该方法接收两个参数:一个整数数组nums和一个整数target。方法的目的是在nums数组中找到两个数,使它们的和等于target,并返回这两个数的索引。

解析:

  1. 创建一个长度为2的整数数组ret,用于存储找到的两个数的索引。
  2. 使用两层for循环遍历nums数组。外层循环遍历数组中的每个元素,内层循环从当前元素的前一个元素开始向前遍历。
  3. 如果在内层循环中找到两个数的和等于target,将它们的索引分别存储在ret数组的第0个和第1个位置,并返回ret数组。
  4. 如果遍历完整个数组都没有找到满足条件的两个数,返回ret数组(此时ret数组中的元素未被修改)。

解法二:哈希表

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> hash = new HashMap<>();
        for(int i = 0; i < nums.length;i++){
            int x = target - nums[i];
            if(hash.containsKey(x)){
                return new int[]{i,hash.get(x)};
            }
            hash.put(nums[i],i);
        }
        return new int[]{-1,-1};
    }
}

twoSum该方法接收两个参数:一个整数数组nums和一个整数target。方法的目的是在nums数组中找到两个数,使它们的和等于target,并返回这两个数的索引。

首先,创建一个HashMap(名为hash)来存储数组中的元素及其对应的索引。然后,遍历数组nums,对于每个元素nums[i],计算target减去nums[i]的值(x)。接着,检查hash中是否包含键x。如果包含,说明找到了两个数的和等于target,返回这两个数的索引(i和hash.get(x))。如果不包含,将当前元素nums[i]及其索引i添加到hash中。

如果遍历完数组后仍未找到满足条件的两个数,返回一个包含两个-1的数组。

面试题 01.02. 判定是否互为字符重排

题目链接: 面试题 01.02. 判定是否互为字符重排

在这里插入图片描述

CheckPermutation该方法接受两个字符串参数s1s2,并返回一个布尔值。

方法的功能是检查两个字符串是否为彼此的排列(permutation)。它首先检查两个字符串的长度是否相等,如果不相等则直接返回false。然后,它创建一个长度为26的整型数组hash,用于记录每个字符出现的次数。

接下来,通过遍历字符串s1,将每个字符对应的位置在hash数组中加一。然后,再遍历字符串s2,将每个字符对应的位置在hash数组中减一。如果在遍历过程中发现某个字符在hash数组中的值小于零,说明该字符在s2中出现的次数超过了在s1中出现的次数,因此返回false

如果遍历完两个字符串后没有发现任何问题,说明两个字符串是彼此的排列,返回true

以下是代码的解析:

class Solution {
    public boolean CheckPermutation(String s1, String s2) {
        if (s1.length() != s2.length()) {
            return false;
        }
        int[] hash = new int[26];
        for (int i = 0; i < s1.length(); i++) {
            hash[s1.charAt(i) - 'a']++;
        }
        for (int i = 0; i < s2.length(); i++) {
            hash[s2.charAt(i) - 'a']--;
            if (hash[s2.charAt(i) - 'a'] < 0) {
                return false;
            }
        }
        return true;
    }
}

217. 存在重复元素

题目链接: 217. 存在重复元素

在这里插入图片描述

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> hash = new HashSet<>();
        for(int s : nums){
            if(hash.contains(s)){
                return true;
            }
            hash.add(s);
        }
        return false;
    }
}

containsDuplicate该方法接受一个整数数组nums作为参数。方法的目的是检查数组中是否存在重复的元素。

代码中使用了一个HashSet来存储已经遍历过的元素。对于数组中的每个元素s,首先检查HashSet中是否已经包含了该元素。如果包含,说明存在重复元素,返回true。如果不包含,将该元素添加到HashSet中。

如果遍历完整个数组后都没有发现重复元素,则返回false

219. 存在重复元素 II

题目链接: 219. 存在重复元素 II

在这里插入图片描述
在这里插入图片描述

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Map<Integer,Integer> hash = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            if(hash.containsKey(nums[i])){
                if(i - hash.get(nums[i]) <= k){
                    return true;
                }
            }
            hash.put(nums[i],i);
        }
        return false;
    }
}

这段代码的功能是检查一个整数数组 nums 中是否存在两个相同的元素,且这两个相同元素的索引之间的差值不超过一个给定的整数 k

具体来说,方法 containsNearbyDuplicate 接受两个参数:

  1. int[] nums: 一个整数数组。
  2. int k: 一个非负整数,表示允许的最大索引差。

方法通过使用一个哈希表(在 Java 中是 HashMap)来跟踪每个数字最后出现的位置。算法如下:

  1. 初始化一个空的 HashMap,用于存储数组中的数字及其对应的最新索引。

  2. 遍历数组 nums 中的每个数字 nums[i]

  3. 对于每个数字 nums[i],检查它是否已经在 HashMap 中存在:

    • 如果不存在,将该数字和其索引 i 添加到 HashMap 中。
    • 如果存在,获取该数字之前记录的索引 lastIndex,并计算当前索引 ilastIndex 的差值。
  4. 如果这个差值小于或等于 k,则返回 true,表示找到了两个索引差不超过 k 的相同元素。

  5. 如果遍历完整个数组后没有找到这样的元素对,则返回 false

这个方法可以用于解决一些与数组中重复元素位置有关的问题,例如在滑动窗口内查找重复项等。

49. 字母异位词分组

题目链接: 49. 字母异位词分组

在这里插入图片描述

  1. 算法概述

    • 遍历输入字符串列表。
    • 对于每个字符串:
      • 将其转换为字符数组。
      • 对字符数组进行排序。
      • 创建一个键,将排序后的字符数组转换回字符串。
      • 如果该键尚不存在于映射中,则为该键创建一个新列表。
      • 将原始字符串添加到与该键对应的列表中。
    • 从映射中提取结果,返回值为一组同字母异序词的列表。
  2. 解释

    • 代码使用一个名为 hashMap<String, List<String>> 来存储同字母异序词。
    • 对于每个输入字符串 s
      • s 转换为字符数组(tmp)。
      • 对字符数组进行排序。
      • 创建一个键,将排序后的字符数组转换回字符串。
      • 如果该键尚不存在于映射中,则为该键创建一个新列表。
      • s 添加到与该键对应的列表中。
    • 最后,从映射中返回值(同字母异序词的列表)。
  3. 示例

    • 给定输入:strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
    • 输出:[["bat"], ["nat", "tan"], ["ate", "eat", "tea"]]
  4. 约束条件

    • 1 <= strs.length <= 10^4
    • 0 <= strs[i].length <= 100
    • strs[i] 由小写英文字母组成。
  5. 判断两个字符串是否是字母异位词

  6. 分组

在这里插入图片描述
在这里插入图片描述

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String,List<String>> hash = new HashMap<>();
        // 1.把所有的字符异位词分组
        for(String s : strs){
            char[] tmp = s.toCharArray();
            Arrays.sort(tmp);
            String key = new String(tmp);
            if(!hash.containsKey(key)){
                hash.put(key,new ArrayList());
            }
            hash.get(key).add(s);
        }
        //2. 提取结果
        return new ArrayList(hash.values());
    }
}

代码解释:

1. 定义类和方法:

class Solution {  
    public List<List<String>> groupAnagrams(String[] strs) {

这里定义了一个名为Solution的类,并在其中定义了一个名为groupAnagrams的公共方法,该方法接受一个字符串数组strs作为参数,并返回一个二维列表,其中每个内部列表都包含一组字符异位词。
2. 初始化哈希表:

Map<String,List<String>> hash = new HashMap<>();

使用Java的HashMap数据结构来存储分组。其中键(key)是排序后的字符串,值(value)是一个列表,包含所有与该键对应的原始字符串(即字符异位词)。

3. 分组字符异位词:

for(String s : strs){  
    char[] tmp = s.toCharArray();  
    Arrays.sort(tmp);  
    String key = new String(tmp);  
    if(!hash.containsKey(key)){  
        hash.put(key,new ArrayList());  
    }  
    hash.get(key).add(s);  
}

对于strs数组中的每个字符串s:

  • 首先,将字符串转换为字符数组tmp
  • 然后,对字符数组进行排序,以消除字符顺序的影响。
  • 接着,将排序后的字符数组转换回字符串,作为哈希表的键(key)。
  • 如果哈希表中还没有这个键,则创建一个新的空列表作为值,并将其添加到哈希表中。
  • 最后,将原始字符串s添加到与该键对应的列表中。

4. 提取结果:

return new ArrayList(hash.values());

将哈希表中的所有值(即所有字符异位词的列表)提取出来,并放入一个新的列表中。这个新列表就是最终的结果,它包含了所有分组后的字符异位词。

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

马尔科686

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

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

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

打赏作者

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

抵扣说明:

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

余额充值