代码随想录-Day07-LetCode|454. 四数相加 II|383. 赎金信|15. 三数之和|18梦破碎的地方-四数之和

文章讨论了四个编程问题,涉及四数之和的解决方案,利用哈希表、双指针和剪枝技巧优化算法,强调排序在解决问题中的重要性。
摘要由CSDN通过智能技术生成

454. 四数相加 II

        思路见注释。主要是太累了,他奶奶的去工地干了半天,回来写算法,对比之下,我发现那么热,那么累都抗的下来,这点算法算什么,吃不了学习的苦就得吃生活的苦,现在的我或许更喜欢吃学习的苦吧!

        

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        //定义map集合,分别存储两个数组的和key次数value
        Map<Integer,Integer> hash=new HashMap<>();
        //定义count,存书最终的元祖数量
        int count=0;
        for(int a:nums1){
            for(int b:nums2){
                //getOrDefauat函数的意思是,如果存在key则返回key
                //对应的value,不存在,返回默认值
                hash.put(a+b,hash.getOrDefault(a+b,0)+1);
            }
        }
        //map集合中存储的是两个数组组合之后对应的和以及次数
        for(int a:nums3){
            for(int b:nums4){
                if(hash.containsKey(0-(a+b))){
                    count+=hash.get(0-(a+b));
                }
            }
        }
        return count;
    }
}

383. 赎金信

           思路:就是使用hash表进行判断,跟昨天字母异或差不多,这里使用数组是为了节省内存

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int rlen=ransomNote.length();
        int mlen=magazine.length();
        if(rlen>mlen){
            return false;
        }
        int[] hash=new int[26];
        //便利字符串,将字母作为键,次数作为值
        for(int i=0;i<rlen;i++){
            hash[ransomNote.charAt(i)-'a']++;
        }
        for(int j=0;j<mlen;j++){
            hash[magazine.charAt(j)-'a']--;
        }
        for(int x:hash){
            if(x>0){
                return false;
            }
        }
        return true;
    }
}

15. 三数之和

        双指针的思路,将算法的时间复杂度将第一个阶,排序感觉是这个算法解决本道题的精髓

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        int len=nums.length;
        if(len<3){
            return null;
        }
        List<List<Integer>> result=new ArrayList<>();
        int left;
        int right;
        //首先对数组进行排序
        Arrays.sort(nums);
        //定义双指针left,right指向数组的左右,如果a+b>c
        //rght右移,同理移
        for(int i=0;i<len;i++){
            if(nums[i]>0){
                return result;
            }
            left=i+1;
            right=len-1;
            if(i>0&&nums[i]==nums[i-1]){
                continue;//说明的值重复了就不可以在使用,跳过。
            }
            while(left<right){//如果left==right说明此时只有元素
                int sum=nums[i]+nums[left]+nums[right];
                if(sum>0){
                    right--;
                }else if(sum<0){
                    left++;
                }else{//找到一个结果
                   // temp.add(nums[i]);
                   // temp.add(nums[left]);
                   // temp.add(nums[right]);
                    result.add(Arrays.asList(
                        nums[i],nums[left],nums[right]));
                    //对left和right进行去重
                    while(left<right&&
                          nums[right]==nums[right-1]){
                        right--;
                    }
                    while(left<right&&
                         nums[left]==nums[left+1]){
                        left++;
                    }
                    left++;
                    right--;
                }
            }
        }
        return result;
        
    }
}

18. 四数之和

        三树之和ProMax,昨晚三树之和其实这个Sioux也很好理解

        注*:什么是剪枝操作?

                        一种算法优化,通过某种判断,避免不必要的索引遍历

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result=new ArrayList<>();
        int len=nums.length;
        if(len<4){
            //进行第一次剪枝操作
            return result;
        }
        //对数组进行排序
        Arrays.sort(nums);
        for(int i=0;i<len;i++){
            //进行第二次剪枝
            if(nums[i]>target&&nums[i]>0){
                break;
            }
            //对i进行去重操作,当前nums[i]已经被使用过,所以下一次直接跳过
            if(i>0&&nums[i]==nums[i-1]){
                continue;
            }
            //进入第二层循环
            for(int k=i+1;k<len;k++){
                //进行第三次剪枝
                if(nums[i]+nums[k]>target&&target>=0){
                    break;
                }
                //对k进行去重操作
                if(k>i+1&&nums[k]==nums[k-1]){
                    continue;
                }
                //使用双指针进行判断
                int left=k+1;
                int right=len-1;
                while(left<right){
                    int sum=nums[i]+nums[k]+nums[left]+nums[right];
                    if(sum>target){
                        right--;
                    }else if(sum<target){
                        left++;
                    }else{
                        result.add(Arrays.asList(nums[i],nums[k],nums[left],nums[right]));
                        //添加元素之后需要立即对left和right进行去重操作
                        //注意,如果重复指针就会移动,这时候之前的循环判断条件left<right可能就不成立
                        //所以仍然需要进行判断,这不是多余操作
                         while(left<right&&nums[left]==nums[left+1]){
                            left++;
                         }
                         while(left<right&&nums[right]==nums[right-1]){
                            right--;
                        }
                         //去重结束之后,指针移动搜索下一个目标
                        left++;
                        right--;
                    }
                   
                }
            }
        }
        return result;
    }
}

Create The Code        Change The World!!

                                                                                                                                        ---三条直线围墙

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值