leetcode哈希表刷题整理

使用的语言是java

第242题. 有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
在这里插入图片描述
思路:这个题可以定义一个26长度的数组,首先用来统计s的字母出现个数(出现一个字母,对应位++),然后跟t中出现字母作比较(出现一个字母,对应位–),最后看数组是否位上全为0即可,我是把这两个字符串排序后比较……,其实是用的库函数,偷懒了

class Solution {
    
    
    public boolean isAnagram(String s, String t) {
    
    
    	//将s,t转化为Char数组,排序后,再转回string
        char[] ss = s.toCharArray();
        Arrays.sort(ss);
        s = String.valueOf(ss);
        char[] tt = t.toCharArray();
        Arrays.sort(tt);
        t = String.valueOf(tt);
        //比较
        if(s.equals(t)) return true;
        return false;
    }
}

第349题. 两个数组的交集

题意:给定两个数组,编写一个函数来计算它们的交集。
在这里插入图片描述
输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。

思路:
主要注意,1.选定创建数组长度min(l1,l2),和最终的数组长度count
2.set中不会出现重复元素,不需要去重
其他没有啥,本题就是一道练习set性质和常用函数的简单题

class Solution {
    
    
    public int[] intersection(int[] nums1, int[] nums2) {
    
    
    	//获取nums1,nums2长度并且创建临时数组
        int l1 = nums1.length;
        int l2 = nums2.length;
        int min_len = l1<l2?l1:l2;
        int[] result = new int[min_len];
        int count = 0;
        //将nums1中元素保存到set中
        Set set1 = new LinkedHashSet();
        for (int i=0;i<l1;i++){
    
    
            set1.add(nums1[i]);
        }
        //遍历l2中的每一个元素,查看是否在set中,如果检查到了,在set中移除,并添加到临时数组中
        for (int i=0;i<l2;i++){
    
    
            if (set1.contains(nums2[i])){
    
    
                result[count] = nums2[i];
                count++;
                set1.remove(nums2[i]);
            }
        }
        //生成真正的返回数组
        int[] res = Arrays.copyOf(result,count);
        return res;
    }
}

202. 快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。

如果 n 是快乐数就返回 True ;不是,则返回 False 。
在这里插入图片描述
思路:如果一个数要不是快乐数,要不不是快乐数,如果不是就会无限循环,那么只要观测到有循环,就可以确定不是,因此可以一直对这个数进行快乐数判定的操作,并且将结果保存在set中,一旦有一次结果在set中出现,就是循环,就不是快乐数,如果有一次结果变成了1,那就是快乐数,使用这两个条件约束,避免出现死循环的情况

class Solution {
    
    
    public boolean isHappy(int n) {
    
    
        Set set = new LinkedHashSet();
        while(true){
    
    
        	//快乐数操作
            int count = 0;
            int tmp = n;
            while(tmp!=0){
    
    
                count += (tmp%10)*(tmp%10);
                tmp=tmp/10;
            }
            //检查结果是否为1和检查结果是否在set中
            if (count == 1) return true;
            else if(set.contains(count)) return false;
            //都不是,则将结果加入到set中
            else {
    
    
                set.add(count);
                n = count;
            }
        }
    }
}

第1题. 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
在这里插入图片描述
思路:两层for循环可以做,但是使用map就是一层for循环 on2变成了on

class Solution {
    
    
    public int[] twoSum(int[] nums, int target) {
    
    
        Map<Integer,Integer> map = new HashMap<Integer, Integer>();
        for (int i=0;i<nums.length;i++){
    
    
        	//如果key有与该数相加为target的值,则返回
            if (map.get(target-nums[i])!=null){
    
    
                return new int[]{
    
    map.get(target-nums[i]),i};
            }
            //否则,将该位置的值,和位置信息作为key,value传入map中
            map.put(nums[i],i);
        }

        throw new IllegalArgumentException("No two sum solution");
    }
}

454. 四数相加 II

给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。

「例如:」

输入: A = [ 1, 2] B = [-2,-1] C = [-1, 2] D = [ 0, 2]

输出: 2

「解释:」

两个元组如下:

(0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
(1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0

思路:a+b之和作为一个map c+d之和作为一个map,然后对两个map进行比较,得出结果。
用A+B+C作为一个,D单独作为一个也不是不行,但是时间复杂度变为on3,会超时

class Solution {
    
    
    public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
    
    
        int n = A.length;
        Map<Integer,Integer> map1 = new HashMap<Integer,Integer>();
        //遍历a,b数组,计算所有a[i]+b[j]的和,并把它们以和为key,出现次数为value的形式保存在map中
        for (int i=0;i<n;i++){
    
    
            for (int j=0;j<n;j++){
    
    
                map1.put(A[i]+B[j],map1.getOrDefault(A[i]+B[j],0)+1);
                
            }
        }

        Map<Integer,Integer> map2 = new HashMap<Integer,Integer>();
        //遍历c,d数组,所做事情同上
        for (int i=0;i<n;i++){
    
    
            for (int j=0;j<n;j++){
    
    
                map2.put(C[i]+D[j],map2.getOrDefault(C[i]+D[j],0)+1);
                
            }
        }

        int count = 0;
        //遍历map1.看map2中是否有对应和为0的key,若有,计算次数
        for (int key:map1.keySet()){
    
    
            if (map2.get(-key)!=null){
    
    
                count += map1.get(key) * map2.get(-key);
            }
        }
        return count;
    }
}

第383题. 赎金信

给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。

(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)

「注意:」
你可以假设两个字符串均只含有小写字母。

canConstruct(“a”, “b”) -> false canConstruct(“aa”, “ab”) -> false canConstruct(“aa”, “aab”) -> true

思路:使用map统计字符串中字符个数,然后比较两个字符串生成的map,看map是否符合逻辑

class Solution {
    
    
	//使用map统计字符串中字符个数
    public static Map<Character,Integer> string2Map(String str){
    
    
        Map<Character,Integer> map = new HashMap<Character,Integer>();
        
        char[]  charArray = str.toCharArray();
        for (char c:charArray){
    
    
            map.put(c,map.getOrDefault(c,0)+1);
        }
        
        return map;
    }
    public boolean canConstruct(String ransomNote, String magazine) {
    
    
        Map<Character,Integer> map1 = string2Map(ransomNote);
        Map<Character,Integer> map2 = string2Map(magazine);
        //根据逻辑比较两个map
        for (char c:map1.keySet()){
    
    
            if (map2.get(c)==null || map2.get(c)<map1.get(c)){
    
    
                return false;
            }
        }
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_38857307/article/details/113998123
今日推荐