代码随想录训练营day06, 哈希表:有效的字母异位词, 两个数组的交集, 快乐数, 两数之和

今天正式开始哈希算法的学习, 之前没有学过, 所以要花点时间在基本概念上, 注意数组就是简单的哈希表。

有效的字母异位词

总体思路:利用哈希表数组, 创建一个26位大小数组, 然后利用ascii码表将题目里的信息输入到table里, 一个用来++, 一个用来--, 最后判断table是否为0

(使用数组解的前提是题目限制了数组的大小)

新知识:

1. s.charAt(i)是用来返回字符串在i位置的值, 大小写看清楚

2.他这里用s.charAt - 'a'就会自动计算index数字, 所以table【xxx】++意思就是在第i个位置加1

细节:

1. 这里的‘a’必须要用单引号

2. 其实有三个for遍历, 第一个遍历加数字, 第二个遍历减数字, 第三个遍历用来判断table是否为0. 注意:要不等于0弹出false得写在里面

3. 当获得字符串的大小的时候要加括号 s.length()

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

两个数组的交集

总体思路: 遍历第一个然后全部转换为哈希表, 然后同样遍历第二个, 注意是去重, 如果之前出现过就放到result集合里(注意, 这里只要创建一个set1数组, 一个result set数组)

新知识:

1. 创建一个hashset需要如下: Set<Integer> set = new HashSet<>(); 注意大小写

2. 将结果集合转为数组: return resSet.stream().mapToInt(x -> x).toArray();

补充细节:

增强for循环:

这里的循环时int i :nums1, 也就是说i是数组nums1的一个元素

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> resSet = new HashSet<>();
        for(int i : nums1){
            set1.add(i);
        }
        for(int i : nums2){
            if(set1.contains(i)){
                resSet.add(i);
            }
        }
        return resSet.stream().mapToInt(x -> x).toArray();
    }
}

普通循环:
这里的i是索引,所以里面加的内容都要变成nums[i]

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> resSet = new HashSet<>();
        //遍历数组一
        for(int i = 0; i < nums1.length; i++){
            set1.add(nums1[i]);
        }
        //遍历数组二, 用contain比较
        for(int i = 0; i < nums2.length; i++){
            if(set1.contains(nums2[i])){
                resSet.add(nums2[i]);
            }
        }
        return resSet.stream().mapToInt(x -> x).toArray();
    }
}

这个也可以使用数组解决, 但是限制太多, 所以就不多阐述了。

快乐数
思路总结: 分为两部分

第 1 部分我们按照题目的要求做数位分离,求平方和

第 2 部分可以使用哈希集合完成。每次生成链中的下一个数字时,我们都会检查它是否已经在哈希集合中。

如果它不在哈希集合中,我们应该添加它。 如果它在哈希集合中,这意味着我们处于一个循环中,因此应该返回 false。

(我们使用哈希集合而不是向量、列表或数组的原因是因为我们反复检查其中是否存在某数字。检查数字是否在哈希集合中需要 O(1)O(1) 的时间,而对于其他数据结构,则需要 O(n)O(n) 的时间)

细节:
1. 写一个方法getNext, 要先定义一个digit计算个位, 然后再定义一个十位数用 +=sum

2. 回到boolean方法, 定义哈希数组放入数据, 判断, n不为1, 同时没有重复的, 否则return

3.getNext方法是return sum, 这个sum就是新的n

class Solution {
    public boolean isHappy(int n) {
    //利用HashSet来确认是否有数组重复
        Set<Integer> hash =  new HashSet<>();
        while(n != 1 && !hash.contains(n)){
            hash.add(n);
            n = getNext(n);
        }
        return n == 1;
    }
    //创建求出个位平方和十位平方的和
    private int getNext(int n){
        int sum = 0;
        while(n > 0){
            int digit = n % 10;
            sum += digit*digit;
            n = n/10;
        }
     return sum;   
    }
}

容易理解版本:

死循环判断, 等于1, 或者进入循环了

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> arr = new HashSet<>();
        while(true){
            if(n == 1){
                return true;
            }
            if(arr.contains(n)){
                return false;
            }
            arr.add(n);
            n = getNext(n);
        }
    }
    public int getNext(int n){
        int sum = 0;
        while(n > 0 ){
            int digit = n % 10;
            sum += digit*digit;
            n = n/10;
        }
        return sum;
    }
}

两数之和

当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要首先想到哈希法
总结思路:

temp = target - nums[i], 看temp是否存在哈希表中, 不存在则存入nums[i]和i, 循环, 直到temp存在于哈希表, 然后return temp的索引和这个数的索引

新知识:
1. 创建HashMap: Map<Integer, Integer> = new HashMap<>();

2.map的方法, map.containsKey(), map.put()

3.通过哈希表获得索引, map.get(temp)

细节:
1.创建一个HashMap

2.for遍历数组里所有的数, 然后判断, temp是否已经存在, 存在就直接return两个索引

3. 不存在就放到哈希表里面

class Solution {
    public int[] twoSum(int[] nums, int target) {
        //创建一个哈希表
        Map<Integer, Integer> map =  new HashMap<>();
        //遍历判断
        for(int i = 0; i < nums.length; i++){
            int temp = target - nums[i];
            //如果temp已经存在于哈希表里了, 就return temp索引和当前索引
            if(map.containsKey(temp)){
                return new int[]{map.get(temp),i};
            }
            //如果不存在, 就放入哈希表
            map.put(nums[i],i);
        }
        //遍历完上面的都没有return, 那就直接返回0
        return new int[0];
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值