代码随想录day07

代码随想录day07

454.四数相加II

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int count = 0;
        Map<Integer , Integer> map = new HashMap();
        //将nums1和nums2的和放入map中,值作key,值出现的次数做value
        for(int i : nums1){
            for(int j : nums2){
                int sum = i + j;
                map.put(sum,map.getOrDefault(sum,0) + 1);
            }
        }

        //将nums3与nums4的和与map进行匹配
        //每有一个符合条件的令count+1
        for(int i : nums3){
            for(int j : nums4){
                count += map.getOrDefault(0-i-j,0);
            }
        }

        return count;

    }
}

383.赎金信

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        //ransomNote的长度必须小于magazine
        if(ransomNote.length() > magazine.length()){
            return false;
        }

        //定义一个字母数组,数组的值代表每个字母出现的次数
        int[] num = new int[26];

        //遍历ransomNote数组,其中每出现的每个字母-1
        for(char c : ransomNote.toCharArray()){
            num[c - 'a'] -= 1;
        }
        //遍历magazine数组,其中每出现的每个字母+1
        for(char c: magazine.toCharArray()){
            num[c - 'a'] += 1;
        }

        //num有负数说明不符合条件
        for(int i : num){
            if(i < 0){
                return false;
            }
        }

        return true;
    }
}

15.三数之和

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        // n 为 3,从 nums[0] 开始计算和为 0 的三元组
        return nSumTarget(nums, 3, 0, 0);
    }

    // n 填写想求的是几数之和,start 从哪个索引开始计算(一般填 0),target 填想凑出的目标和
    public List<List<Integer>> nSumTarget(
            int[] nums, int n, int start, int target) {

        int sz = nums.length;
        List<List<Integer>> res = new ArrayList<>();
        // 至少是 2Sum,且数组大小不应该小于 n
        if (n < 2 || sz < n) return res;
        // 2Sum 是 base case
        if (n == 2) {
            // 双指针那一套操作
            int lo = start, hi = sz - 1;
            while (lo < hi) {
                int sum = nums[lo] + nums[hi];
                int left = nums[lo], right = nums[hi];
                if (sum < target) {
                    while (lo < hi && nums[lo] == left) lo++;
                } else if (sum > target) {
                    while (lo < hi && nums[hi] == right) hi--;
                } else {
                    List<Integer> triplet = new ArrayList<>();
                    triplet.add(left);
                    triplet.add(right);
                    res.add(triplet);
                    while (lo < hi && nums[lo] == left) lo++;
                    while (lo < hi && nums[hi] == right) hi--;
                }
            }
        } else {
            // n > 2 时,递归计算 (n-1)Sum 的结果
            for (int i = start; i < sz; i++) {
                List<List<Integer>> sub =
                        nSumTarget(nums, n - 1, i + 1, target - nums[i]);
                for (List<Integer> arr : sub) {
                    // (n-1)Sum 加上 nums[i] 就是 nSum
                    arr.add(nums[i]);
                    res.add(arr);
                }
                while (i < sz - 1 && nums[i] == nums[i + 1]) i++;
            }
        }
        return res;
    }
}

18.四数之和

参考了灵茶山艾府大佬的解法
仿照三数之和的做法有一组,过不去
nums =[1000000000,1000000000,1000000000,1000000000]
target =-294967296

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<>();
        int n = nums.length;
        for (int a = 0; a < n - 3; a++) { // 枚举第一个数
            long x = nums[a]; // 使用 long 避免溢出
            if (a > 0 && x == nums[a - 1]) continue; // 跳过重复数字
            if (x + nums[a + 1] + nums[a + 2] + nums[a + 3] > target) break; // 优化一
            if (x + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) continue; // 优化二
            for (int b = a + 1; b < n - 2; b++) { // 枚举第二个数
                long y = nums[b];
                if (b > a + 1 && y == nums[b - 1]) continue; // 跳过重复数字
                if (x + y + nums[b + 1] + nums[b + 2] > target) break; 
                if (x + y + nums[n - 2] + nums[n - 1] < target) continue; 
                int c = b + 1, d = n - 1;
                while (c < d) { // 双指针枚举第三个数和第四个数
                    long s = x + y + nums[c] + nums[d]; // 四数之和
                    if (s > target) d--;
                    else if (s < target) c++;
                    else { // s == target
                        ans.add(List.of((int) x, (int) y, nums[c], nums[d]));
                        for (c++; c < d && nums[c] == nums[c - 1]; c++) ;
                        for (d--; d > c && nums[d] == nums[d + 1]; d--) ;
                    }
                }
            }
        }
        return ans;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值