代码随想录算法训练营 day 7 |454.四数相加, 383. 赎金信 , 15. 三数之和,18. 四数之和

一、四数相加

题目及代码随想录解析

解题思路

本题要求的是A[i] + B[j] + C[k] + D[l] = 0所以可以转换一下思路,即A[i] + B[j] = 0 -(C[k] + D[l] )。

使用map处理。

(1)用map记录A、B 组的和sum,sum为map的key,sum在A、B 组的和中一共出现的次数为value。

(2)用res记录满足条件的元组个数。

(3)遍历C、D组,若map中能够找到0 -(C[k] + D[l] ),则res+=res+=map.getOrDefault(0-K-I,0).

代码如下:

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int res=0;
        Map<Integer,Integer> map=new HashMap<Integer,Integer>();
        for(int i:nums1){
            for(int j:nums2){
                int sum=i+j;
                map.put(sum,map.getOrDefault(sum,0)+1);
            }
        }
        for(int i:nums3){
            for(int j:nums4){
                res+=map.getOrDefault(0-i-j,0);
            }
        }
        return res;
    }
}

二、赎金信 

题目及代码随想录解析

解题思路

与字母异位数类似,区别是本题第二个字符串的每个字符只能在第一个字符串中使用一次。

这会有两种情况出现:

(1)两个字符串长度相同,也就是第二个字符串中没有重复的字符。

(2)第一个字符串长度小于第二个字符串。

所以解题步骤如下:

(1)遍历第二个字符串并记录每个字母出现的次数。

(2)遍历第一个字符串并在碰到字母(在第二个字符串中出现过)后减1。

(3)遍历 记录字母出现次数的数组res,如果有不为0 的元素,说明不正确。

具体代码如下:

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if(ransomNote.length()>magazine.length()){
            return false;
        }
        int[] record=new int[26];
        for(char c:magazine.toCharArray()){
            record[c-'a']+=1;
        }
        for(char c:ransomNote.toCharArray()){
            record[c-'a']-=1;
        }
        for(int i:record){
            if(i<0)
                return false;
        }
        return true;
    }
}

三、三数之和

题目及代码随想录解析

解题思路

采用双指针法。先将数组排序,然后开始进行遍历相加。

具体代码如下:

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;
            }
            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]));
                while(left<right && nums[right]==nums[right-1]){
                    right--;
                } 
                while(left<right && nums[left]==nums[left+1]){
                    left++;
                }
                right--;
                left++; 
                    }

            }
        }
        return res;
    }
}

四、四数之和

题目及代码随想录解析

解题思路

与三数之和做法类似,不过和从0 变为 target。

在三数之和的基础上再加一层循环判断。

具体代码如下:

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> res=new ArrayList<>();
        for(int k=0;k<nums.length;k++){
            if(nums[k]>target && nums[k]>=0){
                break;
            }
            if(k>0 && nums[k]==nums[k-1]){
                continue;
            }
            for(int i=k+1;i<nums.length;i++){
                if(nums[k]+nums[i]>target && nums[k]+nums[i]>=0){
                    break;
                }
                if(i>k+1 && nums[i]==nums[i-1]){
                    continue;
                }
                int left=i+1;
                int right=nums.length-1;
                while(right>left){
                    long sum=(long)nums[k]+nums[i]+nums[left]+nums[right];
                    if(sum>target){
                        right--;
                    }
                    else if(sum<target){
                        left++;
                    }
                    else {
res.add(Arrays.asList(nums[k],nums[i],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;
    }
    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = {1, 0, -1, 0, -2, 2};
        int target = 0;
        List<List<Integer>> results = solution.fourSum(nums, target);
        for (List<Integer> result : results) {
            System.out.println(result);
        }
    }
}

五、今日收获

前两道题比较好理解,后两道题还是有难度的。后两道题的细节很多,判断条件需要好好考虑,目前我还不能够做到完全不看题解完成后两道题目。

今日学习+解题+博客=2h30min。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值