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

目录

242.有效的字母异位词

349. 两个数组的交集

202. 快乐数

1. 两数之和


242.有效的字母异位词

建议: 这道题目,大家可以感受到 数组 用来做哈希表 给我们带来的遍历之处。

题目链接/文章讲解/视频讲解: 代码随想录

题解思路:

哈希表中的数据结构:set集合、map集合(用来保存一对键值对的数据)、可以把数组当作哈希表去使用
第一:先明确两个概念:
数组是一种线性数据结构,它使用连续的内存空间存储数据,并通过下标来访问其中的元素。
哈希表是一种基于数组的数据结构,它使用哈希函数将数据映射到数组的不同位置上,从而实现常数时间的查找操作。
第二:使用数组用来做哈希表的方法的理解
此时存储字符串中每个字母的出现的个数,数组下标0-25分别一一对应a-z这26个字母的位置,通过遍历字符串,其对应的位置上字母出现的个数是根据给定字符串中每个字符减去小写字母a的ASCII码值(类似哈希函数)先确定字母存储的位置,再将对应位置上的元素+1操作(默认初始化中数组元素的值为0),这样就记录了给定字符串中每个字母出现的次数了,这里使用数组用来做哈希表的方法主要就是模拟了类似哈希函数的每个字符减去小写字母a的ASCII码值的算法。
第三:判断是否是有效字母异位词
先遍历s字符串中每个字母对应数组位置上的个数并自增1,在得到的数组基础上,再去遍历t字符串中每个字母对应数组位置上的个数并减1,如果最后数组中的每个元素都是0,说明这两个字符串就是有效的字母异位词

class Solution {
    public boolean isAnagram(String s, String t) {
        int[] count = new int[26]; //s、t只包含a-z这26个小写字母,因此只需要定义size为26个数组结构去存储每个字符串中每个字符出现的数字即可

        for(int i = 0; i < s.length(); i++){
            count[s.charAt(i) - 'a']++;  //数组下标0-25分别一一对应a-z这26个字母的位置,通过遍历字符串,其对应的位置上字母出现的个数是根据给定字符串中**每个字符减去小写字母a的ASCII码值**(类似哈希函数)先确定字母存储的位置,再将对应位置上的元素+1操作(默认初始化中数组元素的值为0),这样就记录了给定字符串中每个字母出现的次数了
        }

        for(int i  =0; i < t.length(); i++){
            count[t.charAt(i) - 'a']--; //在得到的数组基础上,再去遍历t字符串中每个字母对应数组位置上的个数并减1,如果最后数组中的每个元素都是0,说明这两个字符串就是有效的字母异位词
        }

        for(int element : count){
            if(element != 0){
                return false;
            }
        }

        return true;
    }
}

349. 两个数组的交集

建议:本题就开始考虑 什么时候用set 什么时候用数组,本题其实是使用set的好题,但是后来力扣改了题目描述和 测试用例,添加了 0 <= nums1[i], nums2[i] <= 1000 条件,所以使用数组也可以了,不过建议大家忽略这个条件。 尝试去使用set。

题目链接/文章讲解/视频讲解:代码随想录

题解思路:

哈希表中的数据结构:set集合、map集合(用来保存一对键值对的数据)、可以把数组当作哈希表去使用
本题需要注意以下两点:
第一点:使用Set接口中的HashSet实现类存储数组元素,因为集合中的set接口存储的是无序、不可重复的数据,保存给定数组中的元素具有很好的去重作用,在比较的时候也会很方便,不会重复比较和重复添加
第二点:需要注意的是结果保存在resultSet集合中,但返回的是int类型的数组,所以需要将 HashSet 转换为 int[] 类型的数组

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        HashSet<Integer> resultSet =  new HashSet<>(); //定义一个存储数组交集的hashset集合(存储的元素不可重复)

        HashSet nums1Set = new HashSet(); //定义一个存储nums1数组中去重后的所数据的集合
        for(int i = 0; i < nums1.length; i++){  //遍历数组中的元素存储在集合中
            nums1Set.add(nums1[i]);
        }

        for(int i = 0; i < nums2.length; i++){
            if(nums1Set.contains(nums2[i])){  //检查存储  数组nums1中去重数据后的 集合是否包含nums2中元素,如果返回true则说明包含,则需要添加到result集合中(会自动去重数据)
                resultSet.add(nums2[i]);
            }
        }

        //方法一:Set 接口不支持通过索引来获取元素,因为集合中的元素并没有顺序,也没有固定的位置,可以使用增强for循环遍历,将 HashSet 转换为 int[] 类型的数组
        int[] res = new int[resultSet.size()]; //使用集合使用size() 方法来返回集合中元素的个数
        int i = 0;
        for(int element : resultSet){
            res[i++] = element;
        }
        return res;
        
        //方法二:使用了 stream() 方法将 Set<Integer> 集合转换为一个流对象,然后使用 mapToInt(Integer::intValue) 方法将 Integer 类型的元素映射为 int 类型的值,并使用 toArray() 方法将 IntStream 流转换为 int[] 数组
        // return resultSet.stream().mapToInt(Integer :: intValue).toArray();

    }
}

202. 快乐数

建议:这道题目也是set的应用,其实和上一题差不多,就是 套在快乐数一个壳子

题目链接/文章讲解:代码随想录

题解思路:

哈希表中的数据结构:set集合、map集合(用来保存一对键值对的数据)、可以把数组当作哈希表去使用
本题寻找快乐数主要注意三点:
第一:获取一个正整数上的每位的平方和,在获取到正整数的最后一位需要及时计算该位的平方和,因为n是不断变化的,需要对前面几位数再取模计算此时最后一位的平方和
第二:快乐数如果求每位平方和出现了之前计算的数值,需要立即跳出循环不能再继续计算下去,可能会出现无限循环也计算不出来1的坏结果
第三:只有当没有出现求每位平方和出现了之前计算的数值,而且计算不等于1,才能继续循环重复计算下去,此时一直计算结果会等于1

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

        while(!sumSet.contains(n) && n != 1){  //set集合包含之前计算得到的数,那么立即返回false
            sumSet.add(n);
            n = getNumber(n);
        } //如果set集合不包含之前计算得到的数,重复运算的结果也等于1,那么一直在循环体内重复计算
          //如果set集合包含之前计算得到的数,那么立即跳出循环,因为这会无限循环也始终变不到1,此时n肯定不等于1
        return n == 1;
    }

    public int getNumber(int n){
        //获取一个正整数上每位的平方和
        int sum = 0;
        while(n > 0){ 
            int last = n % 10; //获取正整数的最后一位
            sum += last * last;
            n = n / 10; //获取正整数中除最最后一位剩余的数,当获取到了正整数中第一位数后,那么再除10取商的结果一定为0,此时循环结束,这也是循环条件大于0的原
        }
        return sum;
    }
}

1. 两数之和

建议:本题虽然是 力扣第一题,但是还是挺难的,也是 代码随想录中 数组,set之后,使用map解决哈希问题的第一题。

建议大家先看视频讲解,然后尝试自己写代码,在看文章讲解,加深印象。

题目链接/文章讲解/视频讲解:代码随想录

题解思路:

哈希表中的数据结构:set集合、map集合(用来保存一对键值对的数据)、可以把数组当作哈希表去使用
本题使用Map去存储数据主要清楚两点:
第一点:因为本题需要判断数值中的两个整数相加之和是不是目标值,并且还要返回他们的数组下标,所以可以用map的键值对一一对应保存数据,方便查找并返回对应元素的下标,从而存储在结果数组中返回
第二点:一定要明确map的key值用set集合存储的是无序,不可重复的数据,value值是用collection集合存储的无序,可重复的数据。这里是key键保存元素值,value值保存元素对应下标值的,因为在map中添加键值对时,存储元素值的key键从前往后遍历只存储相同元素位置靠前的元素,比如[2, 2, 3, 6],目标值是8,那么返回的结果数组只能是[1, 3],所以用key键存储元素值有天然的去重效果。也可以反证一把,如果用value值去存储元素值,由于是用collection集合去存储的,说明存储元素的value值可重复的,那么就有存储下标不同的key键对应着有相同的存储元素的value值,此时如果判断存储元素的value值是不是两数相加之和为目标值的其中一个数,获取对应下标的时候也不是很方便,就没办法保证获取到的就是相同元素位置靠前的那个元素的下标了

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        HashMap<Integer, Integer> map = new HashMap<>(); //使用map键值对一一对应存储元素以及对应的下标值,但注意此时key键存储元素值,value值存储下标

        for(int i = 0; i < nums.length; i++){
            int s = target - nums[i]; //遍历数组的每个数,判断两数相加之和为目标值的其中一个数,同时及时保存如果不是其中的数需要及时保存在集合中,以便后面循环判断集合中是不是判断过
            if(map.containsKey(s)){ //如果是两数相加之和为目标值的其中一个数,那么通过键获取对应的保存在结果数组中的下标值
                result[0] = map.get(s);
                result[1] = i;  
            }
            map.put(nums[i], i); //如果存储元素的key键在set集合中没有包含两数相加之和为目标值的其中一个数,那么一定要在每次判断之后添加到map集合中,看是否满足之后两个元素之和为目标值
        }
        return result;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值