代码随想录算法训练营day06|有效的字母异位词、两个数组的交集、快乐数、两数之和

2023.3.20 有效的字母异位词

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

方法1:哈希表

首先肯定需要两个字符串的长度一致。

在长度一致的前提下,将s字符串的内容放入哈希表中key存放字符,value存放出现次数。

随后遍历t字符串,判读单哈希表中是否有对应值,如果有,使value-1

当两个字符串时字母异位词是,哈希表中的value应该全为0.

    public boolean isAnagram(String s, String t) {
        //长度不相等直接排除。
        if(s.length() != t.length()){
            return false;
        }
        //遍历字符串s计入哈希表
        Map<Character,Integer> hashMap = new HashMap<>();
        for(int i = 0;i<s.length();i++){
             hashMap.put(s.charAt(i),hashMap.getOrDefault(s.charAt(i),0) + 1);
        }
        //检查字符串t,更新哈希表
        for(int i = 0;i<t.length();i++){
            hashMap.put(t.charAt(i),hashMap.getOrDefault(t.charAt(i),0) - 1);
        }
        //检查哈希表中的value值是否为0.
        for(int value:hashMap.values()){
            if(value < 0){
                return false;
            }
        }
        return true;
    }

方法2:根据字符不同存入数组

这种方法本质上也是哈希。

由于字符串全部为小写字母,我们可以利用字符之间进行计算的特性,使其与'a'相减,得到的结果应该在0-26之间,作为数组索引,对应的元素存放出现次数。最后判断出现元素出现次数是否符合要求即可。

    public boolean isAnagram(String s, String t) {
        //长度不相等直接排除。
        if(s.length() != t.length()){
            return false;
        }
        //由于全都是小写字母,直接通过字符计算出其对应字母的数字放入数组中来对比即可
        int[] res = new int[26];
        for(char c : s.toCharArray()){
          res[c-'a']++;
        }
        for(char c : t.toCharArray()){
            res[c-'a']--;
        }
        for(int x : res){
            if(x != 0){
                return false;
            } 
        }
        return true;
    }

注意遍历的效率,采用增强for循环遍历效率更高

2023.3.20 两个数组的交集

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

求交集,就是找到两个数组中元素相同的部分,因此我们可以先将一个数组的元素放入哈希表中,随后遍历另外一个数组,检查其元素在哈希表中是否存在,如果存在,就说明有交集。

问题代码:

    public int[] intersection(int[] nums1, int[] nums2) {
        List<Integer> list = new ArrayList<>();
        Set<Integer> hashSet = new HashSet<>();
        for(int x : nums1){
            hashSet.add(x);
        }
        for(int x : nums2){
            if(hashSet.contains(x)){
                list.add(x);
            }
        }
        int[] res = new int[list.size()];
        int i = 0;
        for(Integer x : list){
            res[i++] = x;
        }
        return res;
    }

原因:当nums有多个重复元素时,list中会重复记录其值。因为我们的结果是需要去重的,所以也需要一个哈希表来记录我们的结果。

正确代码:

    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> hashSet1 = new HashSet<>();
        Set<Integer> hashSet2 = new HashSet<>();
        for(int x : nums1){
            hashSet1.add(x);
        }
        for(int x : nums2){
            if(hashSet1.contains(x)){
                hashSet2.add(x);
            }
        }
        int[] res = new int[hashSet2.size()];
        int i = 0;
        for(Integer x : hashSet2){
            res[i++] = x;
        }
        return res;
    }

2023.3.20 快乐数

202. 快乐数 - 力扣(LeetCode)

这道题的关键就是思想。

出现无限循环是有可能的,在这种情况下,类似于环形链表,会有重复的数出现,我们可以将计算后的数计入哈希表中,检测是否有重复的数即可。

那么是否会出现无限增大的情况呢?答案是不会的

当我们的位数超过四位时,它再经过计算后,值的位数会不断变小,最多在3位上无限循环。

因此我们只需要考虑两种情况:

1.循环后变为1。

2.进入无限循环。

根据条件1,我们需要判断计算后的值是否为1即可。

条件2,就需要我们利用哈希表或者快慢指针了,如果计算后哈希表中存在相同的值或者快指针等于了慢指针,就代表进入了无限循环中。

方法1:哈希表

如果有进入死循环,那么每次遍历时使用contains方法一定会返回一个true值。

class Solution {
    public boolean isHappy(int n) {
        //新建一个哈希表
        Set<Integer> hashSet = new HashSet<>();
        while(n != 1 && !hashSet.contains(n)){//循环条件,当前计算结果不为1,并且还没有进入死循环
        hashSet.add(n);
        n = getNextNum(n);
        }
        //退出循环,代表不满足循环条件,有两种情况
        //1:n = 1,返回true
        //2:进入死循环,返回false
        return n == 1;

    }
    //写一个计算快乐数的方法
    public int getNextNum(int n){
        int nextNums = 0;
        while(n != 0){
            //我们需要获取到n的个位的值,通过对10取余获得
            int single = n % 10;
            //减少n的位数,取得下一个值
            n = n / 10;
            nextNums += single*single;
        }
        return nextNums;
    }
}

方法2:快慢指针

快指针每次进行两次快乐数的计算,慢指针计算一次,如果是快乐数,那么快指针一定会先到达快乐数。

注意:初始化是快指针需要指向先进行了一次快乐数计算的值,否则可能同时到达快乐数。

class Solution {
    public boolean isHappy(int n) {
    int fastNum = getNextNum(n);
    int slowNum = n;
    while(fastNum != 1 && fastNum != slowNum){
        fastNum = getNextNum(getNextNum(fastNum));
        slowNum = getNextNum(slowNum);
    }
    return fastNum == 1;

    }
    //写一个计算快乐数的方法
    public int getNextNum(int n){
        int nextNums = 0;
        while(n != 0){
            //我们需要获取到n的个位的值,通过对10取余获得
            int single = n % 10;
            //减少n的位数,取得下一个值
            n = n / 10;
            nextNums += single*single;
        }
        return nextNums;
    }
}

2023.3.20 两数之和

1. 两数之和 - 力扣(LeetCode)

和为目标值,意思就是目标值减去当前元素的值再数组中是否存在,我们可以把这个是否存在的问题转化为哈希表中的是否有重复值问题。

即遍历数组,在遍历时就将其放入哈希表(题目中已经说了每种输入只会对应于一个答案,因此排除了存在重复元素相关结果的情况),并检查目标元素减去当前元素在哈希表中是否存在,如果存在,就返回对应的下标。

由于这道题涉及到值的判定以及下标的输出,因此我们需要使用HashMap来实现。

    public int[] twoSum(int[] nums, int target) {
        //首先进行
    Map<Integer,Integer> hashMap = new HashMap<>();
    //记录结果的数组
    int[] res = new int[2];
    for(int i = 0;i<nums.length;i++){
        if(hashMap.containsKey(target-nums[i])){
            res[0] = hashMap.get(target - nums[i]);
            res[1] = i;
        }
        else{
            hashMap.put(nums[i],i);
        }
    }
    return res;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值