思路
使用哈希法的经典题目
用一个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
};