刷算法Leetcode---3(哈希表篇)

前言

        本文是根据代码随想录中哈希表内容的顺序进行的  代码随想录

        其他文章链接:刷算法Leetcode文章汇总 

哈希表篇

242.有效的字母异位词

        ①使用 Map 或 26位int数组 统计每种字符的个数

        ②比较两串字符排序结果,应该一样

349.两个数组的交集

        ①两个Set,一个找两个数组的重合字符,另一个保存结果,再将Set转为Array返回

        ②排序+双指针,两指针字符相同且与上一个匹配字符不同,就加入

202.快乐数

完成计算一个数位平方和的算法,使用%和/操作

此题关键在于,找到快乐数的规律,平方和永远达不到1是因为进入了死循环(详细见官方对每种位数平方和的验证),因此问题转换为是否进入循环

        ①Set判断重复,是否进入循环

        ②快慢指针,判断是否相遇

        ③数学方法,证明只存在唯一一个循环,先找到循坏中的所有数,判断实际是否遇到

1.两数之和

        ①暴力求解,双重循环

        ②Map存储value-index,找target-value是否存在,返回下标

454.四数相加Ⅱ

        ①暴力求解超时

        ②分组,两个Map,分记录一二组和三四组的每种sum-num,再对其中一个Map找另一个Map中的-sum,求种数乘积和

        ③分组,一个Map记录一二组的每种sum-num,遍历三四找到对应-num3-num4的种数,求和

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int num = 0;
        Map<Integer,Integer> sum = new HashMap<>();
        for(int a : nums1){
            for(int b : nums2){
                sum.put(a+b, sum.getOrDefault(a+b, 0)+1);
            }
        }
        for(int c : nums3){
            for(int d : nums4){
                if(sum.containsKey(-c-d))num += sum.get(-c-d);
            }
        }
        return num;
    }
}

383.赎金信

长度边界值判断

        ①使用 Map 或 26位int数组 统计magazine中的字符数,再对Note中的每个字符数-1

        ②排序+双指针,字符相同都后移,不同只移动magazine的指针,判断note的指针是否在最后

15.三数之和

要求三元组值不重复,可以排序后遍历,要求当前指针的值与指针前一个值不相等

        ①排序+暴力三重循环,超时

        ②排序+双指针,先确定第一个数,剩下两个使用双指针在有序数组中找到目标和

优化:第一个数确定后

        1)如果nusm[i]+nums[i+1]+nums[i+2]>target,此后遍历不会有等于结果,直接返回

        2)如果nusm[i]+nums[n-2]+nums[n-1]<target,当前nums不会有满足结果,进入下一个循环

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        int n = nums.length;
        Arrays.sort(nums);
        for(int i = 0; i < n; i++){
            if(i+2<n&&nums[i]+nums[i+1]+nums[i+2]>0)return res;
            if(nums[i]+nums[n-1]+nums[n-1]<0)continue;
            if(i > 0 || nums[i] == nums[i-1])continue;
            int z = n-1;
            int target = -nums[i];
            for(int j =i+1;j<n;j++){
                if(j ==i+1||nums[j]!=nums[j-1]){
                    while(j<z&&nums[j]+nums[z]>target)z--;
                    if(j==z)break;
                    if(nums[j]+nums[z]==target)
                        res.add(Arrays.asList(nums[i], nums[j], nums[z]));
                }
            }
        }
        return res;
    }
}

18.四数之和

与上一个题三数之和类似,先排序再判断是否与前一个重复

        ①排序+暴力四重循环,超时

        ②排序+双指针,与三数之和不同的是,每次确定前两个数,另外两个使用双指针

优化:分两种情况:确定第一个数(找另三个数) 和 确定前两个数(找另两个数)

        1)与随后 三 / 两 个数的和大于target,break

        2)与最后 三 / 两 个数的和小于target,continue;

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        if(nums==null||nums.length<4)return res;
        Arrays.sort(nums);
        int n = nums.length;
        for(int i = 0; i < n-3; i++){
            if(i>0&&nums[i]==nums[i-1])continue;
            if((long)nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target)break;
            if((long)nums[i]+nums[n-3]+nums[n-2]+nums[n-1]<target)continue;
            for(int j=i+1;j<n-2;j++){
                if(j>i+1&&nums[j]==nums[j-1])continue;
                if((long)nums[i]+nums[j]+nums[j+1]+nums[j+2]>target)break;
                if((long)nums[i]+nums[j]+nums[n-2]+nums[n-1]<target)continue;
                int l = j+1, r=n-1;
                while(l<r){
                    if(l>j+1&&nums[l]==nums[l-1]){l++;continue;}
                    if(r<n-1&&nums[r]==nums[r+1]){r--;continue;}
                    long sum = (long)nums[i]+nums[j]+nums[l]+nums[r];
                    if(sum==target){
                        res.add(Arrays.asList(nums[i],nums[j],nums[l],nums[r]));
                        l++;
                        r--;
                    }
                    else if(sum<target)l++;
                    else r--;
                }
            }
        }
        return res;
    }
}

哈希表总结:

        1、Map可用于value-index,或者value-sum

        2、统计个数,使用Map或者数组,特别是对于26个小写字母,可以使用26位int数组计数

        3、判断重复/循环,使用Set

        4、对于数和问题,两位数之和使用Map记录value-index,三位/四位数之和使用排序+双指针,四位数之和Ⅱ(不考虑重复问题)使用Map记录sum-num

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值