454.四数相加II
383.赎金信
15.三数之和
18.四数之和
454. 四数相加II
- 我的思路:对于 n1+n2+n3+n4=0 有3种组合情况,n1=-n2 && n3=-n4 etc,可以遍历数组运用哈希表记录出现的情况来做。(但好像有点复杂了...
- 误区:1. 没有把重点放在可重复;2. 多种组合情况只是解法组合,不用都考虑;3. 没有想明白用哈希表记录什么。
- 正解:先找两个数组的和并记录其次数,再遍历另外两个数组来匹配。
var fourSumCount = function(nums1, nums2, nums3, nums4) {
const map = new Map();
for (let i=0; i<nums1.length; i++) {
for (let j=0; j<nums2.length; j++) {
const sum = nums1[i] + nums2[j];
if (map.has(sum)) {
map.set(sum, map.get(sum) + 1);
} else {
map.set(sum, 1);
}
}
}
let res = 0;
for (let i=0; i<nums3.length; i++) {
for (let j=0; j<nums4.length; j++) {
const sum = nums3[i] + nums4[j];
if (map.has(-sum)) {
res += map.get(-sum);
}
}
}
return res;
};
383. 赎金信
var canConstruct = function(ransomNote, magazine) {
const arr = new Array(26).fill(0);
for (const r of ransomNote) {
arr[r.charCodeAt() - 'a'.charCodeAt()] += 1;
}
for (const m of magazine) {
const idx = m.charCodeAt() - 'a'.charCodeAt();
if (arr[idx] !== 0) {
arr[idx] -= 1;
}
}
let res = true;
for (const a of arr) {
if (a !== 0) return false;
}
return res;
};
15. 三数之和
- 我的思路:三指针递归找满足条件的数组
- 缺陷:1. 去重的方法很笨,果然超时;2. 想到了排序,但没有灵活运用到排序带来的好处。
- 正解:1. 排序后双指针可根据相对大小调整位置;2. 对每个组成元素考虑去重
var threeSum = function(nums) {
let res = [];
nums.sort((a,b) => a-b);
for (let i=0; i<nums.length; i++) {
if (nums[i] > 0) return res;
if (i>0 && nums[i] === nums[i-1]) continue;
let l = i+1;
let r = nums.length-1;
while(l < r) {
if (nums[i] + nums[l] + nums[r] > 0) r--;
else if (nums[i] + nums[l] + nums[r] < 0) l++;
else {
res.push([nums[i], nums[l], nums[r]]);
while(r > l && nums[r] === nums[r-1]) r--;
while(l < r && nums[l] === nums[l+1]) l++;
r--;
l++;
}
}
}
return res;
};
18.四数之和
- 我的思路:排序后a和d作为最外圈包围,b和d作为内层区间不断收缩和去重找解
- 缺陷:a和d一起收缩,会遗漏掉a不变而需要d变的场景
- 正解:固定a,移动b,以b为可变区间起点移动c和d。** 剪枝时注意只剪正数情况
var fourSum = function(nums, target) {
if (nums.length < 4) return [];
nums.sort((a,b) => a-b);
const res = [];
for (let i=0; i<=nums.length-1; i++) {
if (nums[i] >= 0 && nums[i] > target) break;
if (i > 0 && nums[i] === nums[i-1]) continue;
for (let k = i+1; k<nums.length-1; k++) {
if (nums[i] + nums[k] > target && nums[i] + nums[k] >= 0) break;
if (k > (i+1) && nums[k] === nums[k-1]) continue;
let l = k+1, r = nums.length-1;
while (l < r) {
const sum = nums[i] + nums[k] + nums[l] + nums[r];
if (sum > target) {
r--;
} else if (sum < target) {
l++;
} else {
res.push([nums[i], nums[k], nums[l], nums[r]]);
while(l<r && nums[r] === nums[r-1]) r--;
while(l<r && nums[l] === nums[l+1]) l++;
r--;
l++;
}
}
}
}
return res;
};