day10 四数之和II |赎金信|三数之和|四数之和

力扣

思路

使用哈希法的经典题目

用一个map存储

遍历a b数组

key放a b 两数之和,value放a b 两数之和出现的次数。

再遍历c d 数组

看0-(c+d)是否在map中出现过,出现的话就count+出现次数

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number[]} nums3
 * @param {number[]} nums4
 * @return {number}
 */
var fourSumCount = function(nums1, nums2, nums3, nums4) {
// let map = {} 这样不行 
// let n = nums1.length
// // 遍历 A B 统计两个数组的元素之和 和出现的次数
// for(let i = 0;i<n;i++){
//     for(let j=0;j<n;j++){
//         map[nums1[i]+nums2[j]]++
//     }
// }
// let count = 0
// for(let i = 0;i<n;i++){
//     for(let j=0;j<n;j++){
//         if(map[0-(nums3[i]+nums4[j])]!==undefined)
//         // 统计出现次数
//         count+=map[0-(nums3[i]+nums4[j])]
//     }
// }
// return count
const twoSumMap = new Map();
let count = 0;

for (const n1 of nums1){
    for(const n2 of nums2){
        const sum = n1+n2
        twoSumMap.set(sum,(twoSumMap.get(sum)||0)+1)
    }
}

for(const n3 of nums3){
    for(const n4 of nums4){
        const sum = n3+n4
        count+=(twoSumMap.get(0-sum)||0)
    }
}
return count
};

问题

这题别用 let map = {} 因为map[]要加加 会出现undefined+1 为NaN

创建一个Map 

const Map = new Map()

ES6 新增数据结构 Map 存储映射关系

Map.set(key,value)

Map.get(key) 根据key获取Map中的value

value没有的话 

count+=(twoSumMap.get(0-sum)||0)

赎金信

力扣

和字母异位词一个思路

用哈希法来做 

定义数组 记录每个字符出现的次数,ransomNote 数组里的+  另一个- 

如果最后遍历record数组 有>0的 说明不能被构成

/**
 * @param {string} ransomNote
 * @param {string} magazine
 * @return {boolean}
 */
var canConstruct = function(ransomNote, magazine) {
    // 求 a ASCII码
    let base = "a".charCodeAt()
    let record = new Array(26).fill(0)

    for(let i=0;i<ransomNote.length;i++){
        let num = ransomNote[i].charCodeAt()//调用函数 +()
        record[num-base]++
    }

    for(let j=0;j<magazine.length;j++){
        let num = magazine[j].charCodeAt()
        record[num-base]--
    }

    for(let i=0;i<26;i++){
        if(record[i]>0)
        return false
    }
    return true
};

问题

求字符的ASCII 码

"a".charCodeAt()  得加()

 不然函数没有被调用

三数之和

力扣

思路

双指针法 

将数组排序 for循环 

从下标0开始 同时定义left=i+1 right=数组结尾位置

在数组中找a b c 和为0

如何移动left right

和>0 r左移(升序的)

<0 l右移

= 加入数组

对 a去重  

bc去重 放到找到一个三元组后 

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function (nums) {
  // 哈希法
  // 两层for循环可以确定a b 的值 可以使用哈希法来确定0-(a+b)是否在 数组里面出现过 但这题要去重 很麻烦 容易超时

  // 双指针法怎么做 高效一点
  // 得对数组进行排序
  const res = [],
    len = nums.length;
  nums.sort((a, b) => a - b); //数组升序排序
  for (let i = 0; i < len; i++) {
    let l = i + 1,
      r = len - 1,
      iNum = nums[i];
    //    排过序 升序
    if (iNum > 0) return res;
    if (iNum == nums[i - 1]) continue; //a去重
    while (l < r) {
      let lNum = nums[l],
        rNum = nums[r],
        threeSum = iNum + lNum + rNum;
      if (threeSum < 0) l++;
      else if (threeSum > 0) r--;
      else {
        res.push([iNum, lNum, rNum]);
        //    去重
        while (l < r && nums[l] == nums[l + 1]) l++;
        while (l < r && nums[r] == nums[r - 1]) r--;
        l++;
        r--;
      }
    }
  }

  return res;
};

问题

排序函数怎么弄

对sort方法的说明

无参数情况:直接调用sort()方法,如果不传入比较函数,默认以字典排序的顺序为结果。

2 传入比较函数:具体返回结果与比较函数有关

四数之和

和三数之和类似  双指针法  只不过多了一层for循环

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[][]}
 */
var fourSum = function(nums, target) {
const len = nums.length;
nums.sort((a,b)=>a-b);
const res = []

for(let i=0;i<len-3;i++){
    // i 去重
    if(i>0&&nums[i]===nums[i-1])continue
    for(let j=i+1;j<len-2;j++){
        // j去重
        if(j>i+1&&nums[j]===nums[j-1])continue
        let l = j+1,r=len-1;
        while(l<r){
            const sum = nums[i]+nums[j]+nums[l]+nums[r]
            if(sum<target)l++
            else if(sum>target)r--
            else{
                res.push([nums[i],nums[j],nums[l],nums[r]])
                while(r>l&&nums[r]===nums[r-1])r--
                while(r>l&&nums[l]===nums[l+1])l++
                r--;
                l++;
            }
        }
    }
}
return res
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值