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

本文介绍了如何使用双指针法解决LeetCode中的四数之和问题,以及将此方法与有效异位词问题进行类比。通过先对数组排序,然后用两个指针遍历查找和为目标值的组合,同时处理重复元素以优化解法。
摘要由CSDN通过智能技术生成

454、四数相加 II

题目链接:力扣题目链接(opens new window)

这个第一次看思路比较混乱,用暴力感觉不够优,暴力的时间复杂度是O(n4)

看了卡哥的思路:

其实和两数之和原理有点类似,只不过改成了先遍历前俩个数组得出和,存入map,在遍历后两个数组,然后找到map中的key,找到之后+对应的count;

根据卡哥思路实现的代码:

var fourSumCount = function (nums1, nums2, nums3, nums4) {
    let sumMap = new Map();
    let count = 0;
    for (let i = 0; i < nums1.length; i = i + 1) {
        for (let j = 0; j < nums2.length; j = j + 1) {
            let sum = 0;
            sum = nums1[i] + nums2[j];
            sumMap.set(sum, (sumMap.get(sum) || 0) + 1);
        }
    }
    for (let m = 0; m < nums3.length; m = m + 1) {
        for (let n = 0; n < nums4.length; n = n + 1) {
            let sum2 = 0;
            sum2 = nums3[m] + nums4[n];
            if (sumMap.get(0 - sum2)) {
                count = count + sumMap.get(0 - sum2);
            }
        }
    }

    return count;
};

383. 赎金信

这个和有效异位词很像,magazine中字母出现次数存在数组中,遍力 ransom note里的字母每次1果这个值小于0,那么说明不能构成返回false.

题目链接: . - 力扣(LeetCode)

实现代码:

var canConstruct = function(ransomNote, magazine) {
const resultArray = new Array(26).fill(0);
  let base = "a".charCodeAt();
  for (let i = 0; i < magazine.length; i = i + 1) {
    resultArray[magazine[i].charCodeAt() - base]++
  }

  for(let j = 0; j < ransomNote.length; j++) {
    resultArray[ransomNote[j].charCodeAt() - base]--
    if(resultArray[ransomNote[j].charCodeAt() - base] < 0) {
        return false
    }
  }
  return true
};

15.三数之和

题目链接:.. - 力扣(LeetCode)

感觉可以试一试双指针法,思路还是要理清一下;

卡哥思路:

用双指针法:先将数组排序,然后定义左指针(I+1)和右指针(nums.length -1) , 如果 num[I]和 num[left] 和 num[right]之和为 0, 那则找到了对应的三个数;

这里要进行一个去重操作;因为原数组里的值可能会有重复的,那么要进行判断 num[i] = num[i-1]的时候应该continue,因为i在前一个相等数的时候,已经把和为0的三个数给找到了,如果继续找,这个值就重复了; 在移动 left 和 right时,也要进行去重,以免下一个值和当前值相等

var threeSum = function (nums) {
    nums = nums.sort((a, b) => a - b);
    let result = [];
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] > 0) break;
        if (i > 0 && nums[i] === nums[i - 1]) continue; // 去重,如果当前数和之前那个数相等,则 continue,因为之前那个数已经找过一遍三数之和是 0 的了
        let left = i + 1, right = nums.length - 1;
        while (left < right) {
            let sum = nums[i] + nums[left] + nums[right];
            if (sum < 0) {
                left++;
            } else if (sum > 0) {
                right--;
            } else {
                result.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 result;
};

18.四数之和

题目链接:. - 力扣(LeetCode)

和三数之和思路一致,多了一层循环

实现代码:

nums = nums.sort((a, b) => a - b )
    let result = []
    for(let k = 0; k < nums.length - 2; k = k + 1) {
        if(k > 0 && nums[k] === nums[k - 1]) continue
        for(let j = k + 1; j < nums.length - 3; j = j + 1) {
            let left = j + 1, right = nums.length - 1
            while(left < right) {
                let forSum = nums[k] + nums[j] + nums[left] + nums[right]
                if(forSum < target) {
                    left = left + 1
                } else if(forSum > target) {
                    right = right - 1
                } else {
                    result.push([nums[k], nums[j], nums[left], nums[right]])
                    while(left < right && nums[left] === nums[left + 1]) {
                        left = left + 1
                    }
                    while(left < right && nums[right-1] === nums[right]) {
                        right = right - 1
                    }
                    left = left + 1;
                    right = right - 1
                }
            }

        }
    }
    return result

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值