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

哈希表理论基础

哈希表

哈希表也叫散列表,数组就是哈希表。
哈希表可以用来快速判断一个元素是否在集合中

哈希函数

哈希函数的作用就是把元素映射到哈希表的索引中,通过索引可以实现快速查找。
在映射的过程中往往会出现把多个元素映射到同一个索引的情况,称为哈希碰撞。哈希碰撞有两种解决方法

  • 拉链法
    • 拉链法的核心思想是把产生哈希碰撞的元素串起来,存在链表中。
  • 线性探测法
    • 线性探测法则是要给产生哈希碰撞的元素重新映射,直到碰撞消失为止。因此一定要保证tableSize大于dataSize。

哈希结构

常见的哈希结构有数组、map和set

242.有效的字母异位词

已完成

思路:

本题需要统计字符串中每个字母的数量,由于字母总共只有26个,因此可以定义长度为26的数组来统计数量。
过程中并不需要直到每个字母的ASCII码,只需要知道与a的差值即可。

代码

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

349. 两个数组的交集

已完成

思路:

本题需要多次去重,第一时间想到set
最后set转为int[]搜了一下:res.stream().mapToInt(x->x).toArray()

代码

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> res = new HashSet();
        Set<Integer> set1 = new HashSet();
        // nums1 去重,得到set1
        for(int value : nums1){
            set1.add(value);
        }

        // 遍历nums2,取出公共部分添加到结果集
        for(int value : nums2){
            if(set1.contains(value)){
                res.add(value);
            }
        }

        return res.stream().mapToInt(x->x).toArray();
    }
}

202. 快乐数

已完成

思路:

第一想法是这道题如果在比赛里可以用查表做。。。
一开始没想到sum会重复出现,用暴力法也能过。

代码

class Solution {
	// 暴力解法
    public int[] split(int n){
        // 将int拆分为数组
        Integer N = Integer.valueOf(n);
        String tempN = N.toString();
        int[] num = new int[tempN.length()];
        for(int i=0;i<tempN.length();i++){
            Character ch =  tempN.charAt(i);
            num[i]=Integer.parseInt(ch.toString());
        }
        return num;
    }
    public boolean isHappy(int n) {
        int sum = n;
        for(int i=0;i<10000;i++){
            int[] num = split(sum);
            // 这里要先把sum清空
            sum=0;
            for(int val : num){
                sum+=val*val;
            }
            if(sum==1) return true;
        }
        return false;
    }
}

判断和是否循环出现的解法

class Solution {
    public int getNextSum(int n){
        int res = 0;
        while(n>0){
            int val = n%10;
            res += val*val;
            n /= 10;
        }
        return res;
    }
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet();
        int sum = n;
        while(true){
            if(sum==1) return true;
            // 和重复出现,直接return false
            if(set.contains(sum)) return false;
            set.add(sum);
            sum = getNextSum(sum);
        }
    }
}

1. 两数之和

已完成

思路:

哈希表的作用是快速判断一个元素是否在集合中,顺着这个往下想
先遍历一遍数组,对于遍历出的每个元素,如果符合条件的另一个数target-nums[i]也存在数组中且不是同一个元素,条件即可满足

代码

class Solution {
    public static ArrayList findIndex(int[] array, int target) {
        // 返回数组中所有target的下标
        ArrayList<Integer> res = new ArrayList();
        for (int i = 0; i < array.length; i++) {
            if (array[i] == target) {
                res.add(i);
            }
        }
        return res;
    }
    public int[] twoSum(int[] nums, int target) {
        int i;
        ArrayList<Integer> array = new ArrayList();
        // 遍历数组
        for(i=0;i<nums.length;i++){
            int minus = target - nums[i];
            // 找到目标元素在数组中的全部位置
            array = findIndex(nums,minus);
            if(array.size()>0){
                if(minus!=nums[i]) return new int[]{i,array.get(0)};
                else{
                    if(array.size()>1){
                        int res = array.get(0) == i?array.get(1):array.get(0);
                        return new int[]{i,res};
                    }
                }
            }
        }
        return new int[]{-1,-1};
    }
}

上面的代码比较繁琐,可以使用map记录下索引位置
这里要注意map中key和value的存储值,key存放元素,value存放元素的索引
因为我们实际需要查询的是元素的索引

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 元素,下标
        Map<Integer,Integer> map = new HashMap<>();    
        for(int i =0;i<nums.length;i++){
            // 目标元素
            int val = target - nums[i];
            // 判断目标元素是否在集合中
            // 由于题目保证有唯一解,可以直接return该解
            if(map.containsKey(val)) return new int[]{i,map.get(val)};
            map.put(nums[i],i);
        }
        return new int[]{-1,-1};
    }
}
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值