DAY6-哈希表,242,349,350,202,1

确实Java集合这个容器的函数使用还不是很熟练,有些函数都不知道有没有,更不用说咋用了,只能说多刷题,把常见的都掌握了,一般手里都要拿一个jdk的API文档。

哈希表(散列表):可以用来快速判断一个元素是否出现在一个集合里,将要存储的值映射在哈希表上涉及到哈希函数(Hash Function),index=hashFunction(name),hashFunction=hashCode(name)%tableSizehashCode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就可以将想要存储的数据映射为哈希表上的索引数字。如果将多个数据映射到哈希表同一个索引上,这就是哈希碰撞,解决方案:1.拉链法,相同索引了在后面成链表,拉链法要选择适当的哈希表大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太长时间。2.线性探测法:要保证tableSize>dataSize,依靠哈希表中的空位来解决碰撞问题,冲突了,就向下找一个空的位置放置数据。

三种哈希结构:数组,set(集合),map(映射)

牺牲空间换取时间。

242

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 i=0;i<26;i++){
            if(record[i]!=0){
                return false;
            }
        }
        return true;
    }

函数:charAt(index),返回指定索引处的char

349

题目中说输出结果去重且不考虑输出顺序。使用set实现哈希表。

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=0;i<nums1.length;i++){
            set1.add(nums1[i]);
        }
        for(int i:nums2){
            if(set1.contains(i)){
                reset.add(i);
            }
        }
        int[] arr = new int[reset.size()];
        int j=0;
        for(int i:reset){
            arr[j++]=i;
        }
        return arr;
//return reset.stream().mapToInt(x->x).toArray();//将结果集合转为数组
    }

350

这道题在力扣上还有进阶的思考题,说要是磁盘内存不能一次性读入所有数据,就要采用哈希的方法去解决。

题解:返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致

排序+双指针

public int[] intersect(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int length1=nums1.length,length2=nums2.length;
        int[] res=new int[Math.min(length1,length2)]; 
        int index1=0,index2=0,index=0;
        while(index1<length1&&index2<length2){
            if(nums1[index1]<nums2[index2]){
                index1++;
            }else if(nums1[index1]>nums2[index2]){
                index2++;
            }else{
                res[index]=nums1[index1];
                index++;
                index1++;
                index2++;
            }
        }
        return Arrays.copyOfRange(res,0,index);
    }

哈希:要同时记录出现的元素和出现的次数,不能用Set,可以数组或者Map

public int[] intersect(int[] nums1, int[] nums2) {
        if(nums1.length>nums2.length){
            return intersect(nums2,nums1);
        }
        Map<Integer,Integer> map=new HashMap<>();
        for(int i:nums1){
            int count = map.getOrDefault(i,0)+1;
            map.put(i,count);
        }
        int[] res=new int[nums1.length];
        int index=0;
        for(int num:nums2){
            int count = map.getOrDefault(num,0);
            if(count>0){
                res[index++]=num;
                count--;
                if(count>0){
                    map.put(num,count);
                }else{
                    map.remove(num);
                }
            }
        }
        return Arrays.copyOfRange(res,0,index);
    }

202:注意怎么找到下一个数。

public boolean isHappy(int n) {
        Set<Integer> set1=new HashSet<>();
        while(n!=1&&!set1.contains(n)){
            set1.add(n);
            n=getnextnumber(n);
        }
        return n==1;
    }
    public int getnextnumber(int n){
        int res=0;
        while(n>0){
            int temp=n%10;
            res=temp*temp+res;
            n=n/10;
        }
        return res;
    }

1:

第三遍了还是没什么思路,要返回索引,就要同时知道索引和对应的值。

使用Key-Value结构,用map来实现哈希表。

那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是valuevalue用来存下标。

map目的用来存放我们访问过的元素,因为遍历数组的时候,需要记录我们之前遍历过哪些元素和对应的下标,这样才能找到与当前元素相匹配的

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++){
            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;
    }

四个点:1.看到两数之和,就想到可以有一个临时值来代表和与遍历到数字的差值,这个临时值出现就能退出程序,用哈希表2.题目中要求返回目标位置的索引,就表示既要知道值又要知道索引,得采用Map结构。

3.本题的map用来存储遍历过的数,用一个临时值表示目标和和当前遍历数的差值,看map(已经遍历过的数值里)集合有没有这个临时值,有的话取出map的值和当前遍历的值一起存进最终要返回的数组里,没有的话把当前值加入map集合里。

4.本题中mapkey用来存数据值,value用来存索引,map.get(key)可以返回value值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值