代码随想录算法打卡-哈希表

文章介绍了如何利用哈希表(数组、set、map)解决字符串中的字母异位词判断、数组交集、两数之和等算法问题,包括数组作为哈希表的使用、滑动窗口技巧以及去重方法的应用。
摘要由CSDN通过智能技术生成

哈希表

1、数组作为哈希表

242.有效字母的异位词

数组是一个简单的哈希表。题目中字符串只有小写字符,那么就可以定义一个数组,来记录字符串s里字符出现的次数(利用了字符的ASCII码可转换为整型)

技巧:只涉及小写字母,考虑用数组作为哈希表

代码实现为:

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

        for(int count:array){
            if(count!=0){
                return false;
            }
        }
        return true;
    }
}

383.赎金信

与上题思路大同小异,只需注意判断哪个字符串的字符是可以多出的,哪个不行即可

代码实现为:

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] array = new int[128];
        for(int i =0;i<ransomNote.length();i++){
            array[ransomNote.charAt(i)]++;
        }
        for(int i =0;i<magazine.length();i++){
            array[magazine.charAt(i)]--;
        }
        for(int count:array){
            if(count>0){
                return false;
            }
        }
        return true;
    }
}

49.字母异位词分组

代码实现为:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String,List<String>> hashmap = new HashMap<>();
        for(String str:strs){
            char[] array = str.toCharArray();
            Arrays.sort(array);
            String key = new String(array);
           List<String> list = hashmap.getOrDefault(key,new ArrayList<String>());
           list.add(str);
           hashmap.put(key,list);

        }
        return new ArrayList<List<String>>(hashmap.values());
    }
}

438.找到字符串中所有字母异位词

结合滑动窗口解决问题

代码实现为:

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int[] need = new int[128];
        int[] window = new int[128];
        List<Integer> res = new ArrayList<>();
        for(int i = 0;i<p.length();i++){
            need[p.charAt(i)]++;
        }

        //移动窗口
        int left = 0,right = 0;
        int count = 0;
        while(right<s.length()){
            char ch = s.charAt(right);
            window[ch]++;
            //更新窗口位置
            //概念别混淆:cbba不是abc的异位词
            while(window[ch]>need[ch]){
                char rem = s.charAt(left);
                window[rem]--;
                left++;
            }
            //保证字符数一致
            if(right-left+1 == p.length()){
                res.add(left);
            }
            right++;

        }
        return res;
    }
}

350.两个数组的交集II

Arrays.copyOfRange() 是 Java 中用于复制指定范围的数组元素到一个新数组的方法

代码实现为:

class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        Map<Integer,Integer> hashmap = new HashMap<>();
        int[] res = new int[nums1.length];
        int index = 0;
        for(int num:nums1){
            hashmap.put(num,hashmap.getOrDefault(num,0)+1);
        }

        for(int num:nums2){
            if(hashmap.containsKey(num) && hashmap.get(num)>0){
                res[index++] = num;
                hashmap.put(num,hashmap.get(num)-1);
            }
        }
        return Arrays.copyOfRange(res,0,index);
    }
}

2、set作为哈希表

349.两个数组的交集

代码实现为:

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set = new HashSet<>();
        Set<Integer> resSet = new HashSet<>();
        int n = Math.min(nums1.length,nums2.length);
        int[] res = new int[n];

        for(int num:nums1){
            set.add(num);
        }
        for(int num:nums2){
            if(set.contains(num)){
                resSet.add(num);
            }
        }
        //set转为数组
        return resSet.stream().mapToInt(x->x).toArray();
    }
}

202.快乐数

代码实现为:

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
        while(set.add(n)){
           n = nextNumber(n);  
        }
       
        return n==1;
    }

    private int nextNumber(int n){
        int res = 0;
        while(n>0){
            int tmp = n%10;
            res += tmp*tmp;
            n = n/10;
        }
        return res;
    }
}

3、map作为哈希表

1.两数之和

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> hashmap = new HashMap<>();
        for(int i = 0;i<nums.length;i++){
            if(hashmap.containsKey(target-nums[i])){
                return new int[]{i,hashmap.get(target-nums[i])};
            }
            hashmap.put(nums[i],i);
        }
        return new int[0];
    }
}

454.四数相加II

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        //哈希表key记录两数组之和,value记录次数
        Map<Integer,Integer> hashmap = new HashMap<>();
        int res = 0;

        for(int num1:nums1){
            for(int num2:nums2){
            int sum = num1+num2;
                hashmap.put(sum,hashmap.getOrDefault(sum,0)+1);
            }
        }

        for(int num3:nums3){
            for(int num4:nums4){
                if(hashmap.containsKey(0-num3-num4)){
                    res += hashmap.get(0-num3-num4);
                }
            }
        }
        return res;
    }
}

4、其他

15.三数之和

与上题不同,本题需要去重,若用哈希表会十分复杂,故采用双指针方法

代码实现为:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
       List<List<Integer>> res = new ArrayList<>();
       Arrays.sort(nums);

       for(int i = 0;i<nums.length;i++){
        if(nums[i]>0){
                return res;
            }
            //nums[i]去重
            if(i>0 && nums[i]==nums[i-1]){
                continue;
            }
        int left = i+1,right = nums.length-1;
        while(left<right){
            int sum = nums[i]+nums[left]+nums[right];
            if(sum>0){
                right--;
            }else if(sum<0){
                left++;
            }else{
                res.add(Arrays.asList(nums[i],nums[left],nums[right]));
                //nums[left]、nums[right]去重
                while(left<right && nums[right]==nums[right-1])right--;
                while(left<right && nums[left]==nums[left+1])left++;
                //先去重,再动指针
                right--;
                left++;
            }
        }
       } 
       return res;
    }
}

18.四数之和

与上题类似

代码实现为:

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);

        for(int i = 0;i<nums.length;i++){
            if(nums[i]>0 && nums[i]>target){
                    return res;
                }
            //给nums[i]去重
            if(i>0 && nums[i]==nums[i-1]){
                continue;
            }
            for(int j = i+1;j<nums.length;j++){
                //给nums[j]去重
                if(j>i+1 && nums[j]==nums[j-1]){
                    continue;
                }
                int left = j+1,right = nums.length-1;
                while(left<right){
                 long sum = nums[i]+nums[j]+nums[left]+nums[right];
                 if(sum>target){
                    right--;
                 }else if(sum<target){
                    left++;
                 }else{
                    res.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));
                    //给nums[left]、nums[right]去重
                    while(right>left && nums[right]==nums[right-1])right--;
                    while(right>left && nums[left]==nums[left+1])left++;
                    right--;
                    left++;
                 }
                }
            }
        }
        return res;
    }
}

  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值