算法打卡:第三章 哈希表part01

1. 今日收获:哈希表理论基础、字母异位词、数组交集、快乐数、两数之和

2. 哈希表理论基础:

(1)哈希算法通过原来的值来确定其存储位置

(2)应用场景:判断元素是否存在集合中;去除重复(set元素和map的键相同只会添加一次)

(3)常用的数据结构:数组(桶计数的思想,适合元素较少且连续的情况),set集合(适合元素数较多,或者元素不连续较分散的情况),map(key对应value)

3. 有效的字母异位词

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

思想:用长度为26的数组来存储a-z字母的出现次数,遍历一个字符串,如果出现则数组对应元素加1;遍历另外一个字符串,出现对应的字母则数组元素减1。最后比较数组的元素是否全为0

方法:

class Solution {
    public boolean isAnagram(String s, String t) {
        int[] capital = new int[26];  // 26个位置对应字母a-z出现的次数

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

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

        // 如果数组的元素为0,对应字母数量相等
        for (int i=0;i<capital.length;i++){
            if (capital[i]!=0){
                return false;
            }
        }

        return true;
    }
}

总结:因为小写字母a-z数量较少且连续,所以适合用数组来判断对应字母是否出现。另外可以直接用字符减去‘a’字符来对应数组下标。

4. 两个数组的交集

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

思想:先遍历一个数组将其中的元素添加到set集合中,再遍历另外一个数组判断其元素是否出现在集合中,如果出现则是两个数组的交集。注意结果也需要去重。

方法:

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        // 首先遍历一个数组,利用集合去重其中的元素
        HashSet<Integer> numSet = new HashSet<>();  
        HashSet<Integer> arr=new HashSet<>();  // 结果也需要去重

        for (int i=0;i<nums1.length;i++){
            if (!numSet.contains(nums1[i])){
                numSet.add(nums1[i]);
            }
        }

        // 判断集合中的元素是否同时存在nums2中
        for (int i=0;i<nums2.length;i++){
            if (numSet.contains(nums2[i])){
                arr.add(nums2[i]);
            }
        }

        // 遍历赋值返回数组
        int[] result=new int[arr.size()];
        int k=0;
        for (int num: arr ){
            result[k++]=num;
        }

        return result;
    }
}

总结:因为本题要求结果也不能重复,所以首先用set集合存储结果,将set集合赋值给数组需要用增强for一个个赋值给数组的元素。

5. 快乐数

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

思想:不断地求数组各个位置数字的平方和,如果为1则是快乐数,如果重复了之前的结果就不是快乐数。

方法:

class Solution {
    public boolean isHappy(int n) {
        // 判断是否会无限循环
        HashSet<Integer> numSet = new HashSet<>();
        boolean flag=false;

        while(true){
            int temp=getSquar(n);
            if (temp==1){  // 快乐数
                flag=true;
                break;
            }else{  // 不是1
                if (numSet.contains(temp)){  // 无限循环了
                    flag=false;
                    break;
                }else{
                    numSet.add(temp);
                    n=temp;
                }
            }
        }
        return flag;
    }

    // 获取每个位置上的数字的平方和
    public int getSquar(int num){
        int result=0;
        while (num!=0){
            int temp=num%10;
            result+=temp*temp;
            num/=10;
        }
        return result;
    }
}

总结:解题的关键在于题目中的”无限循环“,所以set集合还可以用来判断元素是否出现过。相同情况如果用数组或列表则需要从头遍历到尾,要熟练掌握不同数据结构地特点,发挥其最大长处。

6. 两数之和:

题目链接:1. 两数之和 - 力扣(LeetCode)

思想:定义map存储元素的值和对应下标。遍历数组元素,判断当前数和target之间的差值。如果差值存在map中,则返回当前下标和差值对应的value;如果差值不存在,则将当前遍历元素和下标放入map中。

方法:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // map中的key不会重复,value是数组下标
        HashMap<Integer,Integer> map=new HashMap<>();
        int[] result=new int[2];

        for (int i=0;i<nums.length;i++){
            int other=target-nums[i];  
            if (map.containsKey(other)){  // 另一个数存在
                result[0]=i;
                result[1]=map.get(other);
            }else{  // 另一个数不存在
                map.put(nums[i],i);
            }
        }

        return result;
    }
}

总结:map存储了数组元素和对应的下标值,同时map的键不能重复,也满足题目要求。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值