优选算法---哈希表

1.两数之和

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

题目解析:找出nums中和等于target的两个数字,并返回这两个数字的下标

算法讲解:

解法一:暴力枚举

此时的暴力枚举的顺序有点不同,此时是从固定位置从后往前去寻找有没有等于target-nums[i]的数字,代码实现:

java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int n=nums.length;
        int[] ret=new int[2];
        for(int i=0;i<n;i++){
            int need=target-nums[i];
            for(int j=i-1;j>=0;j--){
                if(nums[j]==need){
                    ret[0]=i;
                    ret[1]=j;
                    break;
                }
            }
        }
        return ret;
    }
}

解法二:利用哈希表优化

暴力枚举哪里需要优化呢?优化的点就在于每次在固定的位置去寻找need时,都需要从前往后遍历一遍去寻找need,此时可以优化寻找need的这一过程

优化的思路:利用哈希表,每次遍历到nums数组中的一个数字,都先从哈希表找一下need,如果有则直接返回,如果没有,就将这个数字存储到哈希表中,继续遍历下一个数字

代码实现:

java 复制代码
class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> hash=new HashMap<>();
        int n=nums.length;
        int[] ret=new int[2];
        for(int i=0;i<n;i++){
            int need=target-nums[i];
            if(hash.containsKey(need)){
                ret[0]=i;
                ret[1]=hash.get(need);
                break;//一个小优化点
            }
            hash.put(nums[i],i);
        }
        return ret;
    }
}

2.面试题 01.02. 判定是否互为字符重排

题目解析:判断一个字符串经过重新排列后能否变成另一个字符串

算法讲解:利用哈希表

如果一个字符串的字符串经过重新排列之后能够变成另一个字符,说明两个字符串对应的字符数量是一样的,则此时就可以用哈希表来记录每个字符出现的情况

解法一:利用两个哈希表

创建两个哈希表,一个用来记录s1中字符出现的情况,另一个用来记录s2中字符出现的情况,最后用过遍历其中一个字符串,去判断两个哈希表中的对应字符的value是否相等即可,如果不相等,此时直接返回false即可

代码实现:

java 复制代码
class Solution {
    public boolean CheckPermutation(String s1, String s2) {
        Map<Character,Integer> hash1=new HashMap<>();
        Map<Character,Integer> hash2=new HashMap<>();
        char[] ch1=s1.toCharArray();
        char[] ch2=s2.toCharArray();
        if(ch1.length > ch2.length) return false;
        if(ch2.length > ch1.length) return false;
        for(int i=0;i<ch1.length;i++){
            hash1.put(ch1[i],hash1.getOrDefault(ch1[i],0)+1);
        }
        for(int i=0;i<ch2.length;i++){
            hash2.put(ch2[i],hash2.getOrDefault(ch2[i],0)+1);
        }
        for(int i=0;i<ch1.length;i++){
            if(hash1.get(ch1[i])!=hash2.get(ch1[i])) return false;
        }
        return true;
    }
}

解法二:在解法一思路的基础上进行优化,利用一个哈希表即可,这个哈希表用来记录其中一个字符串中字符出现的数量,然后去遍历另一个字符串,然后让哈希表中对应的value--,如果发现hash[ch[i]-'a']<0,说明此时不符合题目要求,此时知己返回false即可

代码实现:

java 复制代码
class Solution {
    public boolean CheckPermutation(String s1, String s2) {
        int[] hash=new int[26];
        char[] ch1=s1.toCharArray();
        char[] ch2=s2.toCharArray();
        if(ch1.length > ch2.length) return false;
        if(ch2.length > ch1.length) return false;
        for(int i=0;i<ch1.length;i++){
            hash[ch1[i]-'a']++;
        }
        for(int i=0;i<ch2.length;i++){
            hash[ch2[i]-'a']--;
            if(hash[ch2[i]-'a']<0) return false;
        }
        return true;
    }
}

3.存在重复元素

题目链接:217. 存在重复元素 - 力扣(LeetCode)

题目解析:判断nums数组中是否存在相同元素,如果存在相同元素,则返回true,否则返回false

算法讲解:哈希表

通过哈希表存储nums数组中各元素出现次数的信息,每次遍历到一个元素时,就去哈希表中去判断一下这个元素之前是否存在,如果存在,此时直接返回true,如果不存在,则将该数字存到哈希表中,继续遍历下一个数字

代码实现:

java 复制代码
class Solution {
    public boolean containsDuplicate(int[] nums) {
        Map<Integer,Integer> hash=new HashMap<>();
        for(int x:nums){
            if(hash.getOrDefault(x,0)>0) return true;
            hash.put(x,hash.getOrDefault(x,0)+1);
        }
        return false;
    }
}

4.存在重复元素 II

题目链接:219. 存在重复元素 II - 力扣(LeetCode)

题目解析:判断nums数组中是否存在两个索引i和j,且满足nums[i]==nums[j]且abs(i-j)<=k,如果有,则返回true,否则返回true

算法讲解:哈希表

小细节:如果发现有nums[i]==nums[j]的情况,但是出现j-i>k的情况,此时就说明i太小了,不符合题目要求,则此时可以大胆得将哈希表中的i替换为j

代码实现:

java 复制代码
class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Map<Integer,Integer> hash=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            if(hash.containsKey(nums[i])){
                int prev=hash.get(nums[i]);
                if(i-prev<=k){
                    return true;
                }else{
                    hash.put(nums[i],i);
                }
            }
            hash.put(nums[i],i);
        }
        return false;
    }
}

5.字母异位分词

题目链接:49. 字母异位词分组 - 力扣(LeetCode)

题目解析:如题

算法讲解:哈希表

这道题的重点就是如何设计哈希表,因为互为字母异位词的两个字符串的字符的数量和种类是一模一样的,也就是说互为字母异位词的两个字符串通过ASCII排序后的两个字符串是完全相同的字符串,此时就可以将哈希表的key设计为String类型,而value就是List<String>类型

知道如何设计哈希表后,这道题就有两个步骤

第一个步骤:判断是否互为字母异位词,此时可以通过排序的方式来判断

第二步骤:将哈希表中的所有value返回即可

代码实现:

java 复制代码
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String,List<String>> hash=new HashMap<>();
        for(String str:strs){
            char[] ch=str.toCharArray();
            Arrays.sort(ch);
            String s=new String(ch);
            if(hash.containsKey(s)){
                hash.get(s).add(str);
            }else{
                List<String> tmp=new ArrayList<>();
                tmp.add(str);
                hash.put(s,tmp);
            }
        }
        return new ArrayList<>(hash.values());
    }
}
相关推荐
疑惑的杰瑞2 小时前
掌握 C 语言流程控制:分支、循环、goto 与表达式求值详解
c语言·开发语言·算法·算术转换
im_AMBER2 小时前
Leetcode 85 【滑动窗口(不定长)】最多 K 个重复元素的最长子数组
c++·笔记·学习·算法·leetcode·哈希算法
B_lack0262 小时前
字节转换算法应用_读取本地时间
数据结构·算法·数组·西门子plc·博途·时间处理·scl
leiming62 小时前
c++ string 容器
开发语言·c++·算法
wljun7393 小时前
六、OrcaSlicer 切片之区域
算法·切片软件 orcaslicer
2401_841495643 小时前
【LeetCode刷题】跳跃游戏Ⅱ
数据结构·python·算法·leetcode·数组·贪心策略·跳跃游戏
leaves falling3 小时前
动态规划讲解
算法·动态规划
钓鱼的肝3 小时前
GESP系列(3级)小杨的储蓄
开发语言·数据结构·c++·笔记·算法·gesp
MicroTech20254 小时前
MLGO微算法科技推出人工智能与量子计算融合新成果:基于QLSS与LCHS的量子DPM算法技术
人工智能·科技·算法