总结一下,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!
哈希表是根据关键码的值而直接进行访问的数据结构。
而一般哈希表都是用来快速判断一个元素是否出现在集合里。
哈希函数的功能就是将某些内容映射为哈希表上的索引,然后就可以通过查询索引来快速查看这些内容了。
常见的三种哈希结构
1.数组
2.set(集合)
3.map(映射)

242.有效的字母异位词

普通版

public boolean isanagram(String s,String t) {

          if(s.length()!=t.length()) {
                 return false;
             }
             int[] arr=new int[26];
             for(int i=0;i<s.length();i++) {
                 arr[s.charAt(i)-'a']++;
                             arr[t.charAt(i)-'a']--;
             }

             for(int i=0;i<26;i++) {
                 if(arr[i]!=0)
                 return false;
             }
             return true;    
     }

进阶版

    if(s.length()!=t.length()) {
             return false;
         }
         Map<Character,Integer> table=new HashMap<Character,Integer>();
         for(int i=0;i<s.length();i++) {
             char ch=s.charAt(i);
             table.put(ch, table.getOrDefault(ch,0)+1);
         }
         for(int i=0;i<t.length();i++) {
             char ch=t.charAt(i);
             table.put(ch, table.getOrDefault(ch, 0)-1);
             if(table.get(ch)<0) {
                 return false;
             }
         }
         return true;
}

思路简述

这个题其实就是看两个字符串所包含字母是否相同,关键就是利用哈希表的思想来解答,设置一个长度为26的数组当作哈希表。每一个下标存储的内容代表对应字母出现次数。然后判断遍历完两个字符串之后,会不会有存储的内容不为0,如果有,则返回false;
进阶版的问如果含有unicode怎么办,解决办法就是用map进行存储。

202.快乐数

1.哈希法

public int getInt(int num){
    int sum=0;
    int ans;
    while(num>0) {
        ans=num%10;
        num/=10;
        sum+=ans*ans;
    }
    return sum;    
}
public boolean isHappy1(int num) {
    Set<Integer> table=new HashSet<>();
    while(num!=1&&!table.contains(num)) {//数字既不等于1,而且又没有出现过
        if(!table.contains(num)) {
            table.add(num);
        }
        num=getInt(num);
    }
    return num==1;
}

思路简述

分析题目可知,数字要么最后到达1,要么一直困在一个循环里。所以实质上是判断会不会出现循环。哈希法的关键就在于设立一个set来进行判断,看看数字是否已经出现过,如果出现过,那么就注定出现循环了。

2.快慢指针法

public int getInt(int num){
    int sum=0;
    int ans;
    while(num>0) {
        ans=num%10;
        num/=10;
        sum+=ans*ans;
    }
    return sum;    
}
public boolean isHappy(int num){
    int fast=getInt(num);
    int slow=num;
    while(fast!=1&&fast!=slow) {
        slow=getInt(slow);
        fast=getInt(getInt(fast));//注意fast指针设置两倍速的方式
    }
    return fast==1;
}

思路简述

本题实际上是对是否会有循环的判断,也就是对是否会出现环的一个判断,那么就可以想起来用快慢指针方法进行判断的思路,如果出现环,那么快慢指针就会相遇。按照这个基本思路进行求解。

454.四数相加2

public int foursumcount(int[] a,int[] b,int[] c,int[] d) {
    Map<Integer,Integer> table=new HashMap<Integer,Integer>();
    for(int i=0;i<a.length;i++) {
        for(int j=0;j<b.length;j++) {
            int ans=a[i]+b[j];
            table.put(ans, table.getOrDefault(ans, 0)+1);
        }
    }
    int count=0;
    for(int i=0;i<c.length;i++) {    
        for(int j=0;j<d.length;j++) {
            if(table.containsKey(0-(c[i]+d[j]))) {
                count+=table.get(0-(c[i]+d[j]));
            }
        }
    }
    return count;
}

思路简述

本题的解题关键就是设立一个map,其key保存ab数组任意两数之和,其value保存这个两数之和出现的次数。
然后判断这个map里是不是有key等于(0-c[i]-d[j])的,也就是等于cd数组任意两数之和的倒数。并设立一个计数器count,如果有,就加上这个key对应的value。

349.两个数组的交集

public int[] interSection(int[] nums1,int[] nums2) {

    Set<Integer> set1=new HashSet<Integer>();
    Set<Integer> set2=new HashSet<Integer>();
    for(int i:nums1) {
        set1.add(i);
    }
    for(int i:nums2) {
        if(set1.contains(i)) {//将nums1和nums2都有的元素保存在set2
            set2.add(i);
        }
    }
    int[] ans=new int[set2.size()];
    int count=0;
    for(int i:set2) {//将set移到数组里
        ans[count++]=i;
    }
    return ans;    
}

思路简述

这道题比较简单,就是找两个数组相同的值并存储。


leetcode      哈希 快慢指针

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!