代码随想录算法训练营第 5 天(哈希表1)| 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法

数据小用数组,数据大用set,数据比较散用map

一、242.有效的字母异位词

题目:242. 有效的字母异位词 - 力扣(LeetCode)

视频:学透哈希表,数组使用有技巧!Leetcode:242.有效的字母异位词_哔哩哔哩_bilibili

讲解:代码随想录

思路

a-z 的 ASCll 码是连续的,用字母减去 a 的 ASCll 码的就是每个字母的码

1.计数数组:使用一个长度为26的数组(假设字符串只包含小写字母)来记录每个字母出现的次数。

2. 统计字符出现次数

  • 遍历第一个字符串,将其中的每个字符出现的次数加1。
  • 遍历第二个字符串,将其中的每个字符出现的次数减1。

3 检查计数数组:最后检查计数数组中的所有元素是否都为0。如果是,则说明两个字符串是字母异位词;否则不是。

charAt() 此方法返回位于字符串的指定索引处的字符。该字符串的索引从零开始。

class Solution {
    public boolean isAnagram(String s, String t) {
        int[] record = new int[26];

        for(int i=0; i<s.length(); i++){
            record[s.charAt(i) - 'a']++;
        }

        for(int i=0; i<t.length(); i++){
            record[t.charAt(i) - 'a']--;
        }
        
        for(int count: record){
            if(count != 0) return false;
        }
        return true;
    }
    
}

二、349. 两个数组的交集

题目:349. 两个数组的交集 - 力扣(LeetCode)

视频:学透哈希表,set使用有技巧!Leetcode:349. 两个数组的交集_哔哩哔哩_bilibili

讲解:代码随想录

思路:

1、 初始化两个哈希集合

  • 第一个集合用于存储第一个数组中的所有元素。 set1
  • 第二个集合用于存储两个数组的交集结果。reSet

2. 遍历第一个数组

  • 将第一个数组中的所有元素添加到第一个哈希集合中。

3. 遍历第二个数组

  • 对于第二个数组中的每个元素,检查它是否存在于第一个哈希集合中。
  • 如果存在,则将其添加到第二个哈希集合中(为了避免重复,可以使用add方法,因为集合本身不允许重复元素)。

4. 返回结果

  • 将第二个哈希集合转换为数组并返回

HashSet 可以去重

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        if(nums1 == null || nums2 == null || nums1.length == 0 || nums2.length == 0) return new int[0];

        //1
        Set<Integer> set1 = new HashSet<>();   
        Set<Integer> reSet = new HashSet<>();

        ///2 遍历第一个数组,把它放到Set中
        for(int i : nums1){
            set1.add(i);
        }

        //3 遍历第二个数组,检查这个数组中是否存在于第一个哈希集合中,存在就放在新集合reSet中
        for(int i : nums2){
            if(set1.contains(i)){
                reSet.add(i);
            }
        }

        //4
        return reSet.stream().mapToInt(x->x).toArray();
    }
}
return resSet.stream().mapToInt(x -> x).toArray();

4、 这段代码 stream().mapToInt(x -> x).toArray() 是Java 8及以上版本中的一个流操作,用于将 Set 转换为 int[] 数组,具体解释如下:

  1. stream():将 Set 转换为一个流(Stream)。流是Java 8引入的一个高级迭代器,允许你以声明式方式处理数据集合。它支持多种操作,如过滤、排序、转换等。
  2. mapToInt(x -> x):这是一个中间操作,用于将流中的每个元素映射为一个 int 类型的值。这里的 x -> x 是一个Lambda表达式,表示将流中的每个元素 x 映射为它自身。由于 Set 中的元素已经是 Integer 类型,这个映射操作实际上没有改变元素的值,只是将 Integer 类型转换为 int 类型。
  3. toArray():这是一个终端操作,用于将流中的元素收集到一个数组中。由于前面的 mapToInt 已经将元素转换为 int 类型,所以 toArray() 会返回一个 int[] 数组。

第 4 步可以用另一种方法:

        //4
        int[] arr = new int[resSet.size()];
        int j = 0;
        for(int i : resSet){
            arr[j++] = i;
        }
        
        return arr;

HashSet常用方法-CSDN博客

Set<Integer> set1 = new HashSet<>();  // 创建一个HashSet
set1.add(i);   //往set1中加元素 将指定元素添加到HashSet中,如果元素已经存在,则不会重复添加
set1.contains(i)  //判断set1中是否含有这个元素 判断HashSet是否包含指定元素。

三、202. 快乐数

题目:202. 快乐数 - 力扣(LeetCode)

视频:

讲解:代码随想录

这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。

判断sum是否重复出现就可以使用 HashSet。

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> record = new HashSet<>();

        while(n!=1 && !record.contains(n)){
            record.add(n);
            n = getNextNum(n);
        }
        return n == 1;       
    }

    private int getNextNum(int n){
            int result = 0;

            while(n > 0){
                int temp = n % 10;
                result += temp * temp;
                n = n/10;
            }

            return result;
        }
}

逐位对数值进行平方计算:

以下是对getNextNum()这三行代码的逐行中文解释:

int d = n % 10;

这行代码的意思是取n除以10的余数,并将其赋值给变量d。这实际上是在获取n的个位数字。例如,如果n是123,那么n % 10的结果就是3,所以d会被赋值为3。

n = n / 10;

这行代码的意思是将n除以10,并将结果重新赋值给n。这一步是为了去掉n的个位数字,以便在下一次循环中处理十位数字。继续上面的例子,如果n原来是123,执行这行代码后,n会变成12。

totalSum += d * d;

这行代码的意思是将d的平方(即d * d)加到totalSum上。totalSum是一个累加器,用于记录所有位数平方和的总和。在我们的例子中,如果d是3,那么d * d就是9,这个值会被加到totalSum上。

综合这三行代码,它们的作用是取出一个整数n的个位数字,计算其平方,并将这个平方值加到一个累加器totalSum上,然后去掉n的个位数字,以便处理下一个位数的数字。这个过程通常在一个循环中进行,直到n变为0,这样就可以计算出n的所有位数平方和的总和。

四、1. 两数之和

题目:202. 快乐数 - 力扣(LeetCode)

视频:梦开始的地方,Leetcode:1.两数之和,学透哈希表,map使用有技巧!_哔哩哔哩_bilibili

讲解:代码随想录

map中key和value分别表示什么?

这道题 我们需要 给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。

那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。

所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。

思路:

1. 初始化一个哈希表:用于存储数组中的元素及其对应的索引。

2. 遍历数组

  • 对于每一个元素nums[i],计算出目标值与当前元素的差值temp = target - nums[i]
  • 检查哈希表中是否存在temp,如果存在,则找到了两个数,返回它们的索引。
  • 如果不存在,则将当前元素及其索引存入哈希表中。
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];

        if(nums == null || nums.length == 0) return result;

        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            int temp = target - nums[i];
            if(map.containsKey(temp)){
                result[1] = i;
                result[0] = map.get(temp);
                break;     //记得加break
            }
            map.put(nums[i], i);
        }
        return result;
        
    }
}

【Java基础】Java中Map集合的常用方法_java map的常用方法-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值