代码随想录Day06 有效的字母异位词 两个数组的交集 快乐数 两数之和

代码随想录Day06| 有效的字母异位词 两个数组的交集 快乐数 两数之和

1.题目链接:有效的字母异位词 - 力扣

文章讲解/视频讲解: https://programmercarl.com/0242.%E6%9C%89%E6%95%88%E7%9A%84%E5%AD%97%E6%AF%8D%E5%BC%82%E4%BD%8D%E8%AF%8D.html

题目描述:给定两个字符串 *s**t* ,编写一个函数来判断 *t* 是否是 *s* 的字母异位词。

**注意:**若 *s**t* 中每个字符出现的次数都相同,则称 *s**t* 互为字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true

示例 2:

输入: s = "rat", t = "car"
输出: false

解题思路:

开辟一个整型数组a存储字母az,因为az的ASCII是连续排列的,所以它们可以按照一定的数字规律储存在数组a里面,0代表a,1代表b,以此类推。然后使用for循环。首先遍历字符串s,出现相应的字母,就在对应的字母下标上加上1。再开辟了一个数组b存储字母a~z,和上面所讲的一样,最后比较ab两个数组的大小,出现了不一样的数字则返回false,没有不一样的,循环完则返回true。

后面在学习的时候发现自己和代码随想录中的思路差不多,但还是多开辟了一个数组,其实可以一加一减,在字符串s中出现的就在数组对应的字母下标中+1,字符串t中出现的就在数组对应的字母下标中-1。最后和0进行比较,不是0就说明t和s不互为字母异位词。这个方法还是很巧妙的,节省了空间。

下面是代码示例:

(开辟了两个数组的):

class Solution{
    public boolean isAnagram(String s, String t) {
        int[] a=new int[26];
        int[] b=new int[26];
        char[] charS=s.toCharArray();
        char[] charT=t.toCharArray();
        int lenS=s.length();
        int lenT=t.length();
        if(s.length()!=t.length()){
            return false;
        }
        for(int i=0;i<lenS;i++){
            a[charS[i]-'a']++;
            b[charT[i]-'a']++;
        }
        for(int i=0;i<26;i++){
            if (a[i] != b[i]) {
                return false;
            }
        }
        return true;
    }
}

(使用一加一减,只开辟了一个数组的):

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;
    }
}

2.题目链接:两个数组的交集 - 力扣

题目描述:给定两个数组 nums1nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

文章讲解/视频讲解:https://programmercarl.com/0349.%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%BA%A4%E9%9B%86.html

解题思路:

之前对哈希没有很了解,所以在做这道题的时候完全没有想到用哈希。主要是我对于java使用哈希的语法还没掌握的很好,后面多花点时间学习。

1.暴力解法:

因为力扣上面给了两个数组里面存储值的大小,所以可以开辟一个数组大小为1001的数组,然后根据所出现的数字,储存到对应的数组下标中去,如果不为0,则++,为1的话则是出现了重复的数字,就不用再++。对于nums2的话,则是遇见了对应的数组下标内储存的数为1的话就++,为1的话就不用++。同时使用一个count来记录出现了多少个重复的数字,用于后续需要返回的数组的大小

代码示例如下:

class Solution{
    public int[] intersection(int[] nums1, int[] nums2){
        int[] a=new int[1001];
        int count=0;
        for(int i=0;i< nums1.length;i++){
            if(a[nums1[i]]==0){
                if(a[nums1[i]]==1){
                    continue;
                }
                else a[nums1[i]]++;
            }
        }
        for(int i=0;i< nums2.length;i++){
            if(a[nums2[i]]==1){
                if(a[nums2[i]]==2){
                    continue;
                }
                else {
                    a[nums2[i]]++;
                    count++;
                }
            }
        }
        int[] b=new int[count];
        int j=0;
        for(int i=0;i<1001;i++){
            if(a[i]==2){
                b[j++]=i;
            }
        }
        return b;
    }
}
2.使用HashSet(学习后)

题目中说明了:输出结果中的每个元素一定是唯一的,也就表示输出的结果没有重复的,而且不需要考虑输出结果的顺序,这个时候就可以考虑使用哈希表。使用HashSet可以将nums1中的出现过的元素构成一个无重复的元素的集合,接着再和nums2进行比较即可。
在这里插入图片描述

补充:HashSet是一个没有重复元素的集合,但是元素的顺序可能会随着时间的改变而改变。 创建HashSet对象 Set< > hs=new HashSet<>(); 添加元素 hs.add()(如果集合中有这个元素,则不会重复添加) 移除元素 hs.remove()

将集合转化为数组:

  1. resSet.stream():将集合resSet转换为一个Stream流,使得我们可以对集合中的元素进行操作。
  2. mapToInt(x -> x):通过mapToInt方法,将Stream中的每个元素x映射为一个int值。在这里,每个元素都保持不变,即转换为自身。
  3. toArray():将Stream流中的元素收集到一个int类型的数组中,并返回该数组。

下面是代码示例:

class Solution3 {
    public int[] intersection(int[] nums1, int[] nums2) {
        if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
            return new int[0];
        }
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> reSet = new HashSet<>();
        //遍历数组
        for (int i : nums1) {
            set1.add(i);
        }
        //遍历数组2的过程中判断哈希表中是否出现了该元素
        for (int i : nums2) {
            if (set1.contains(i)) {
                reSet.add(i);
            }
        }
        return reSet.stream().mapToInt(x -> x).toArray();
    }
}

3.题目链接:快乐数 - 力扣

题目描述:编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n快乐数 就返回 true ;不是,则返回 false

示例 1:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:

输入:n = 2
输出:false

文章讲解/视频讲解:代码随想录 (programmercarl.com)

解题思路:

这道题的解题关键是对于无线循环的解读。题目中说了会无限循环,也就是说再求和的过程中,sum会重复出现,如果它开始重复出现了,那么就说明这个数不是快乐数。

当遇到了要快速判断一个元素是否在集合里面出现时,就需要考虑哈希法。

对于求和计算的方法较为简单,就不单独描述了。

下面是代码示例:

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> record =new HashSet<>();
        while (n!=1&&!record.contains(n)){
            record.add(n);
            n=getNextNumber(n);
        }
        return n==1;
    }
    private int getNextNumber(int n){
        int sum=0;
        while (n>0){
            int temp=n%10;
            sum+=temp*temp;
            n=n/10;
        }
        return sum;
    }
}

4.题目链接:

题目描述:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

文章讲解/视频讲解:代码随想录 (programmercarl.com)

解题思路:

使用哈希表map,储存遍历过的元素。key储存数值,value储存对应的数组的下标。再遍历一个元素的时候,去map中寻找对应的目标元素是否之前遍历过,目标元素等于目标数值-当前遍历的元素的数值。如果map中有则取出来放到数组中并返回。

代码示例如下:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res=new int[2];
        if(nums==null||nums.length==0){
            return res;
        }
        Map<Integer,Integer>map=new HashMap<>();
        for(int i=0;i< nums.length;i++){
            //遍历当前元素,并在map中寻找是否有匹配的key
            int temp=target-nums[i];
            if(map.containsKey(temp)){
                res[1]=i;
                res[0]=map.get(temp);
                break;
            }
            map.put(nums[i],i );
        }
        return res;
    }
}

总结:

今天的题目都不算很难。重点是理解哈希和学习哈希表。后续需要复习和回顾。今天所学习到的新的知识还是很多的。今天较忙,所以写的较为潦草。

  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值