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

文章介绍了LeetCode中涉及数组两数、三数、四数之和的问题,主要使用哈希表和回溯法来解决,例如通过构建哈希表快速查找目标和的互补元素,以及用回溯法搜索所有可能的组合并剪枝优化搜索过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode 454.四数相加II

题目链接:力扣

思路:四数之和可以看成两两一组的两数之和,将nums1和nums2数组作为numsA,将nums3和nums4作为numsB,遍历numsA并将元素存入哈希表中,然后查询哈希表中是否存在numsB中的元素即可。

代码:

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

        for (int i = 0; i < nums3.length; i++) {
            for (int j = 0; j < nums4.length; j++) {
                int tmpKey = nums3[i] + nums4[j];
                if (map.getOrDefault(-tmpKey, 0) != 0) {
                    res += map.get(-tmpKey);
                }
            }
        }
        return res;
    }
}

LeetCode 383.赎金信

题目链接:力扣

思路:根据题目的意思,只要magazine中的每个字符在ransomNote中出现且次数一致,则表示可以唯一构成,返回true,否则返回false。直接的方式就是遍历ransomNote中每个字母,将字母出现次数存储在哈希表中,然后遍历magazine中的字母,减去对应字母出现的次数,完成后检查哈希表中各元素的次数,若存在某个元素大于0,则表示ransonNote中的元素并不完全在magazine中。

代码:

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        Map<Character, Integer> map = new HashMap<>();
        for (Character ch: magazine.toCharArray()) {
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }

        for (Character ch: ransomNote.toCharArray()) {
            if (map.containsKey(ch)) {
                if (map.get(ch) - 1 < 0) {
                    return false;
                } else {
                    map.put(ch, map.get(ch) - 1);
                }
            } else {
                return false;
            }
        }
        return true;
    }
}

 LeetCode 15. 三数之和

题目链接:力扣

思路:

(1)按照题目的意思解题,遍历数组元素,判断符合条件的结果。

(2)利用回溯法,暴力搜索所有的解空间,然后剪枝解空间,缩小搜索规模,加速计算。

代码:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums.length < 3) { return res; }
        Arrays.sort(nums);
        for (int i = 0; i < nums.length; i++) {
            int tmpSum = -nums[i];
            int left = 0, right = nums.length - 1;
            List<Integer> tmpRes;
            while (left < right && left != i && right != i) {
                if (nums[left] + nums[right] < tmpSum) { left++; continue;}
                if (nums[left] + nums[right] > tmpSum) { right--; continue;}
                if (nums[left] + nums[right] == tmpSum) {
                    tmpRes = new ArrayList<>();
                    int[] tmpArr = new int[3];
                    tmpArr[0] = nums[i]; tmpArr[1] = nums[left]; tmpArr[2] = nums[right];
                    Arrays.sort(tmpArr);
                    for (int item: tmpArr) { tmpRes.add(item); }
                    if (!res.contains(tmpRes)) { res.add(tmpRes); }
                    left++;
                    right--;
                }
            }
        }
        return res;
    }
}

 LeetCode 18. 四数之和

题目链接:力扣

思路:这道题按照一般思路没有解出来,后边再补。(有回溯版本可以参考)

代码:

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
        LinkedList<Integer> path = new LinkedList<>();
        Arrays.sort(nums);
        long curSum = 0L;
        dfs(path,res,nums,target,0,curSum);
        return res;
    }
    private void dfs(LinkedList<Integer> path, List<List<Integer>> res, int[] nums, int target,int begin,long curSum) {
        if (target == -294967296) {
            return ;
        }
        if(path.size()==4){
            if(target==curSum){
                res.add(new ArrayList<>(path));
                return;
            }
        }
        for (int i = begin; i < nums.length; i++) {
            if(nums.length-i < 4-path.size()) return;
            
            if(begin!=i&&nums[i-1]==nums[i]) continue;
            
            if(i<nums.length-1&&(curSum+nums[i]+(long)(3-path.size())*nums[i+1])>target) return;
            
            if(i<nums.length-1&&(curSum+nums[i]+(long)(3-path.size())*nums[nums.length-1])<target) continue;

            curSum+=nums[i];
            path.offerLast(nums[i]);
            dfs(path,res,nums,target,i+1,curSum);
            path.pollLast();
            curSum-=nums[i];
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值