攻克代码随想录Day7 | 454. 四数相加 II | 15.三数之和 | 18.四数之和

一、454. 四数相加 Ⅱ

从今天开始我们就得尝试一些更为困难的题目了哈,首先看一下454题的题目介绍:
454. 四数相加II
刚看到这题的时候其实我脑袋里是懵的,后来经过仔细地思考,我认为使用Map去设计是一个不错的想法。

首先,我们先声明一个map,keynums1nums2每个数之和,而value则为该和出现的次数。之后我们再遍历nums3nums4,对于这两个数组,我们应求出 0 - (nums3[k] + nums4[l])在map中的value值,并把它加到我们最终的count上,也就是我们的返回值。

具体代码如下:

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number[]} nums3
 * @param {number[]} nums4
 * @return {number}
 */
var fourSumCount = function(nums1, nums2, nums3, nums4) {
    let map = new Map();
    let count = 0;
    for(let i = 0;i < nums1.length;i++){
        for(let j = 0; j < nums2.length;j++){
            map.set(nums1[i] + nums2[j],(map.get(nums1[i] + nums2[j]) || 0) + 1);
        }
    }
    for(let i = 0;i < nums3.length;i++){
        for(let j = 0;j < nums4.length;j++){
            count += (map.get(0 - (nums3[i] + nums4[j])) || 0);
        }
    }
    return count;
};

二、383. 赎金信

这题整体的思路和 242. 有效的字母异位词很像,本题我们应该采用数组,最后只要最后数组不存在大于0的值就返回true,否则位false。

具体代码如下:

/**
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function(ransomNote, magazine) {
    let arr = new Array(26).fill(0);
    const a_code = "a".charCodeAt();
    for(const a of ransomNote){
        arr[a.charCodeAt() - a_code]++;
    }
    for(const b of magazine){
        arr[b.charCodeAt() - a_code]--
    }
    for(const num of arr){
        if(num > 0){
            return false;
        }
    }
    return true;
};

三、15.三数之和

我们先来看一下题目背景:
在这里插入图片描述
某种程度上讲,三数之和是一道非常具有挑战性的题目。为了解决这一问题,我们采用三指针法进行解题。

首先我们的一步就是排序,排序的时候用的是sort()函数,并在函数里面调用函数compare()。排完序后,nums为从左到右的非递减数列。

这时候我们声明三个指针,第一个指针为i,一开始指向index为0的位置,作用是在for循环中不断遍历。第二个指针为left,指向i + 1的位置。第三个指针为right,指向数组最右侧的数。当三个指针指向的数大于0时候,right指针向左移一格;同理,小于0时往右移一格;等于的时候,返回数组的指针给res,并将left值加1,right值-1.

但做到这一步是远远不够的,因为我们忘记了去重的事宜。首先,在一开始我们要对nums[i]判定,如果其大于0,那就没必要运行后面的代码了。此外,在i>=1的情况,如果其值与nums[i-1]值相同,那么相当于这一类情形我们已经考虑过了,直接continue完事。最后,在三数之和判定为0后,我们要继续判定nums[left+1]和nums[left]nums[right-1]和nums[right]。判定完成后可以方便我们去重。

具体代码如下:

/**
 * @param {number[]} nums
 * @return {number[][]}
 */

var threeSum = function(nums) {
    const res = [];
    nums.sort((a,b) => a - b);
    for(let i = 0;i < nums.length;i++){
        if(nums[i] > 0) return res;
        if(i >= 1 && nums[i] === nums[i - 1]) continue;
        let left = i + 1;
        let right = nums.length - 1;
        while(left < right){
            if(nums[i] + nums[left] + nums[right] < 0){
                left++;
            }
            else if(nums[i] + nums[left] + nums[right] > 0){
                right--;
            }
            else{
                res.push([nums[i],nums[left],nums[right]]);
                while(left < right && nums[left] === nums[left + 1]){
                    left++;
                }
                while(left < right && nums[right] === nums[right - 1]){
                    right--;
                }
                left++;
                right--;
            }
        }
    }
    return res;
};

四、18.四数之和

在这里插入图片描述

这题的大致思路是和三数之和相似的,主要的区别就是得多加一层循环了。其它方面区别倒没有那么大哈。

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function(nums, target) {
    const res = [];
    const len = nums.length;
    nums.sort((a,b) => a-b);
    if(len < 4) return res;
    for(let i = 0;i < len - 3;i++){
        if(i >= 1 && nums[i] === nums[i - 1]) continue;
        for(let j = i + 1;j < len - 2;j++){
            if(j > i + 1 && nums[j] === nums[j - 1]) continue;
            let left = j + 1;
            let right = len - 1;
            while(left < right){
                if(nums[i] + nums[j] + nums[left] + nums[right] > target){
                    right--;
                }
                else if(nums[i] + nums[j] + nums[left] + nums[right] < target){
                    left++;
                }
                else{
                    res.push([nums[i],nums[j],nums[left],nums[right]]);
                    while(left < right && nums[left] === nums[left + 1]){
                        left++;
                    }
                    while(left < right && nums[right] === nums[right - 1]){
                        right--;
                    }
                    left++;
                    right--;
                }
            }
        }
    }
    return res;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值