【算法】代码随想录训练营Day7打卡,leetcode454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和
454.四数相加II
力扣链接:https://leetcode.cn/problems/4sum-ii/submissions/
这道题的解法其实我们可以把四个数组分成两组,然后a,b数组把每一种组合的方式都和和都求出来存储在map中,然后我们遍历c,d数组,当0-(c+d) 在 map中存在时,那就说明这时候 abcd相加为0;这时候记一次数就行了
如图
解法
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var fourSumCount = function(nums1, nums2, nums3, nums4) {
let map = new Map();
let count = 0;
for(const n1 of nums1){
for(const n2 of nums2) {
let sum = n1 + n2;
map.set(sum,(map .get(sum) || 0) + 1)
}
}
for(const n3 of nums3){
for(const n4 of nums4){
const sum = n3 + n4;
count += (map.get(0-sum)||0)
}
}
return count;
}
383. 赎金信
https://leetcode.cn/problems/ransom-note/description/
这道题我们要找magazine 里的字符是否能构成 ransomNote
思路其实也跟前面的几道题很类似,我们用一个map来维护,首先我们要在map中存储magazine内字符出现的次数。然后便利ransomNote,并判断其中的字符是否在map中。
如图
解法
/**
* @param {string} ransomNote
* @param {string} magazine
* @return {boolean}
*/
var canConstruct = function(ransomNote, magazine) {
let map = new Map();
for(item of magazine){
map.set(item,map.has(item)?map.get(item)+1:1); //若map中有 则+1,若没有则设置为1
}
for(item of ransomNote){
if(!map.has(item)) return false; // map中如果没有则返回false
let index = map.get(item);
if(index==0) return false; //如果 map中的值<0了 说明超过了可以使用的值,也返回false
map.set(item,--index);
}
return true;
};
LeetCode 15. 三数之和
https://leetcode.cn/problems/3sum/
JS解法
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
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]
// 数组排过序,如果第一个数大于0直接返回res
if (iNum > 0) return res
// 去重
if (iNum == nums[i - 1]) continue
while(l < r) {
let lNum = nums[l], rNum = nums[r], threeSum = iNum + lNum + rNum
// 三数之和小于0,则左指针向右移动
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
};
18. 四数之和
https://leetcode.cn/problems/4sum/
四数之和和三数之和的思路是一样的,我们一样使用一个双指针法 l r来判断,但是我们要加两层for循环来进行一个遍历,这样就是四数之和了
解法
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
var fourSum = function(nums, target) {
const len = nums.length;
if(len < 4) return [];
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]]);
// 对nums[left]和nums[right]去重
while(l < r && nums[l] === nums[++l]);
while(l < r && nums[r] === nums[--r]);
}
}
}
}
return res;
};
今日心得
今日完成算法+完成文章的总共时间共4小时,三数之和和四数之和的解法很像,稍微拓展一下思路就可以了,赎金信的解题思路可以使用map也可以使用数组,其实解题思路在昨天的题中也是有相像的,总的来说哈希表这一章很多的思路都是相差不多的就是维护一个哈希表,这个哈希表中有一些历史的值,然后我们可以通过哈希表来进行存储,记录等。