题目一 454. 四数相加 II
思路
用hash法,hash存储前两个数字可能的和的次数,再循环遍历后两个数,看hash里相加符合0的次数,整体相加即为所求。
var fourSumCount = function(nums1, nums2, nums3, nums4) {
const hash = {};
for (let i = 0; i < nums1.length; i++) {
for (let j = 0; j < nums2.length; j++) {
let sum = nums1[i] + nums2[j];
if (!hash[sum]) {
hash[sum] = 1;
} else {
hash[sum]++;
}
}
}
let count = 0;
for (let i = 0; i < nums3.length; i++) {
for (let j = 0; j < nums4.length; j++) {
let sum = nums3[i] + nums4[j];
if (hash[0 - sum]) {
count += hash[0 - sum];
}
}
}
return count;
};
题目二 383. 赎金信
思路
比较简单,对magazine做hash,然后遍历ransomNote看hash的值,如果不存在,直接返回false,遍历完成则返回true
var canConstruct = function(ransomNote, magazine) {
const hash = {};
for (let i = 0; i < magazine.length; i++) {
const char = magazine[i];
if (!hash[char]) {
hash[char] = 1;
} else {
hash[char]++;
}
}
for (let i = 0; i < ransomNote.length; i++) {
const char = ransomNote[i];
if (hash[char]) {
hash[char]--;
} else {
return false;
}
}
return true;
};
题目三 15. 三数之和
思路
一层循环+快慢指针,难点在于去重,还想了好大会,但需要举例子才理解。
- a去重:比较i与i-1的大小,并且i大于0,这样前面遍历过的数字不需要再去循环,因为前面的值是包含后面的所有结果的。
- b、c去重:在找到之后,判断是否有相同元素,有的话,left++或者right--,跳过这个元素,不用再做收集。
var threeSum = function(nums) {
nums.sort((a, b) => a - b);
const len = nums.length;
if (nums[0] > 0) {
return [];
}
let result = [];
for (let i = 0; i < len; i++) {
if (i > 0 && nums[i - 1] === nums[i]) {
continue;
}
let left = i + 1;
let right = len - 1;
while (left < right) {
if (nums[i] + nums[left] + nums[right] < 0) {
left++;
} else if (nums[i] + nums[left] + nums[right] > 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. 四数之和
思路
和三数之和类似,但是是两层for循环,加上快慢指针。
var fourSum = function(nums, target) {
nums.sort((a, b) => a - b);
const len = nums.length;
let result = [];
for (let i = 0; i < len - 3; i++) {
if (nums[i] > target && nums[i] > 0) {
break;
}
if (i > 0 && nums[i] === nums[i - 1]) {
continue;
}
for (let j = i + 1; j < len - 2; j++) {
if (nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) {
break;
}
if (j > i + 1 && nums[j] === nums[j - 1]) {
continue;
}
let left = j + 1;
let right = len - 1;
while (left < right) {
const sum = nums[i] + nums[j] + nums[left] + nums[right]
if (sum > target) {
right--;
} else if (sum < target) {
left++;
} else {
result.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 result;
};
总结
脑图总结一波几数之和相关的题目。