代码随想录算法训练营Day6

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

454.四数相加II 题目链接

本题解题步骤:

首先定义 一个Hashmap,key放a和b两数之和,value 放a和b两数之和出现的次数。

遍历A和B数组,统计两个数组元素之和key,和出现的次数value,放到map中。

定义int变量count,用来统计 a+b+c+d = 0 出现的次数。

在遍历C和D数组,如果找到 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。

最后返回统计值 count 就可以了

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int count = 0;
        Map<Integer, Integer> map = new HashMap<>();
        for (int i : nums1){
            for (int j : nums2){
                //如果map中key存在i +j,则+1, 如果不存在则赋值1
                 map.put(i + j, map.getOrDefault(i + j , 0)+ 1);
            }
        }
        for (int i : nums3){
            for (int j : nums4){
                if(map.containsKey(0 - (i + j))){
                    count += map.get(0 - (i + j));
                }
            }
        }
        return count;
    }
}

时间复杂度: O(n)


383. 赎金信 题目链接

用一个长度为26的数组还记录magazine里字母出现的次数,然后再用ransomNote去验证这个数组是否包含了ransomNote所需要的所有字母。

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if (ransomNote.length() > magazine.length()) return false;
        int [] res = new int[26];
        for (char c : magazine.toCharArray(){
            res[c - 'a']++;
        }
        for (char c : ransomNote.toCharArray(){
            res[c - 'a']--;
            if(res[c - 'a'] < 0){
                 return false;
            }       
        }
        return true;
            
    }                                                                                                                            
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

    15. 三数之和 题目链接

    在这里采用双指针法,思路更为直观。需要注意的是去重逻辑与操作。

  • class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            int len = nums.length;
            Arrays.sort(nums);                        //排序
            if (nums == null || len < 3) return res;
            for (int i = 0 ; i < len; i++){
                if (nums[i] > 0)break;             //第一个数都>0 后面全是,不成立
                if (i > 0 && nums[i] == nums[i-1]) continue;  //去重
                
                int l = i + 1, r = len - 1;
                while(l < r){
                    int sum = nums[i] + nums[l] + nums[r];
                    if (sum == 0){
                        res.add(Arrays.asList(nums[i],nums[l],nums[r]));   //保存
                        while (l < r && nums[l] == nums[l + 1]) l++;   //去重
                        while (l < r && nums[r] == nums[r - 1]) r--;
                        l++; r--;
                    }
                    else if (sum > 0) r--;
                    else l++;
                }
            }
            return res;
        }
    }

    18. 四数之和 题目链接

    与三数之和类似,采用双指针法,注意的是去重与剪枝操作

    class Solution {
        public List<List<Integer>> fourSum(int[] nums, int target) {
            List<List<Integer>> res = new ArrayList<>();
            int len = nums.length;
            Arrays.sort(nums);                        //排序
            if (nums == null || len < 4)return res;
    
            for (int i = 0 ; i < len; i++){
                if (nums[i] > 0 && nums[i] > target)break;    //剪枝
                if (i > 0 && nums[i] == nums[i -1])continue;  //去掉重复
    
                for(int j = i + 1; j < len; j++){
                    if (j > i + 1 && nums[j] == nums[j - 1] )continue;  //去重
                    int l = j +1 , r = len - 1;
                    while(l < r){
                        int sum = nums[i] + nums[j] +nums[l] + nums[r];  
                        if(sum < target)l++;            
                        else if(sum > target)r--;
                        else{
                            res.add(Arrays.asList(nums[i],nums[j],nums[l], nums[r]));  // 保存
                            while(l < r && nums[l] == nums[l + 1])l++;   // 去重
                            while(l < r && nums[r] == nums[r - 1])r--;   // 去重
                            l++; r--;
                        }
                    }
                }
            }
            return res;
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值