Leetcode 454.四数相加II
题目:454.四数相加II
初始思路
四个数组求和,可以参考242.有效的字母异位词,四个数组两两分组。
代码
var fourSumCount = function (nums1, nums2, nums3, nums4) {
// key放nums和nums2两数之和,value放两数之和出现的次数。
const map = new Map()
let count = 0
// 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中。
for (let n1 of nums1) {
for (let n2 of nums2) {
const sum1 = n1 + n2
if (map.has(sum1)) {
map.set(sum1, map.get(sum1) + 1)
} else {
map.set(sum1, 1)
}
}
}
// 在遍历nums3和nums4数组,找到如果 0-(n3+n4) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
for (let n3 of nums3) {
for (let n4 of nums4) {
const sum2 = - n3 - n4
if (map.has(sum2)) {
count += map.get(sum2)
}
}
}
return count
};
感想
- 思路参考242.有效的字母异位词
- 要注意map的key和value都存放的是什么,key放nums和nums2两数之和,value放两数之和出现的次数。
- 在遍历的过程中,如果这个和没出现过,次数就设置为1,如果出现过就获取这个和的value值。
- 在遍历nums3和nums4的时候,直接找-(n3+n4)出现的次数即可。
Leetcode 383.赎金信
题目:383.赎金信
初始思路
思路参考242.有效的字母异位词。还是先记录magazine中的字符,然后再ransomNote中对比查找。
代码
var canConstruct = function (ransomNote, magazine) {
if (ransomNote.length > magazine.length) return false
const resSet = new Array(26).fill(0)
const base = 'a'.charCodeAt()
for (let s of magazine) {
resSet[s.charCodeAt() - base]++
}
for (let s of ransomNote) {
// 如果ransomNote中出现了magazine不存在的字符
if (!resSet[s.charCodeAt() - base]) return false
// 使用过就减1,因为magazine中的字符不能出现多次
resSet[s.charCodeAt() - base]--
}
return true
};
感想
- 因为题目说了只有小写字母,所以用数组更方便。
- 要熟练掌握这种题目的写法。
Leetcode 15.三数之和
题目:15.三数之和
初始思路
没什么思路,看到题解才理解一点,但是res数组去重还是有点难理解。
代码
var threeSum = function (nums) {
const res = []
const len = nums.length
if (nums == null || len < 3) return res
// 数组排序
nums.sort((a, b) => a - b)
for (let i = 0; i < len; i++) {
let left = i + 1, right = len - 1
// 如果 nums[i]大于 0,则三数之和必然无法等于 0,结束循环
if (nums[i] > 0) break
// 如果 nums[i] = nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过
if (i > 0 && nums[i] === nums[i - 1]) continue
while (left < right) {
let sum = nums[i] + nums[left] + nums[right]
if (sum < 0) left++
else if (sum > 0) right--
else {
res.push([nums[i], nums[left], nums[right]])
// 当 sum = 0 时,nums[L] == nums[L+1] 则会导致结果重复,应该跳过,L++
while (left < right && nums[left] === nums[left + 1]) {
left++
}
// 当 sum = 0 时,nums[R] == nums[R−1] 则会导致结果重复,应该跳过,R−−
while (left < right && nums[right] === nums[right - 1]) {
right--
}
left++
right--
}
}
}
return res
};
感想
- 使用双指针法,题解:https://leetcode.cn/problems/3sum/solution/hua-jie-suan-fa-15-san-shu-zhi-he-by-guanpengchn/
- 三元组需要做去重操作。这个很细节,贴上代码随想录的截图。
- 时间复杂度:O(n2),从O(n3)降了一阶。
Leetcode 18.四数之和
题目:18.四数之和
初始思路
代码
var fourSum = function (nums, target) {
const res = []
const len = nums.length
if (nums == null || len < 4) return res
// 数组排序
nums.sort((a, b) => a - b)
for (let i = 0; i < len; i++){
// 如果 nums[i] = nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过
if (i > 0 && nums[i] === nums[i - 1]) continue
for (let j = i + 1; j < len - 2; j++){
// 去重
if (j > i + 1 && nums[j] === nums[j - 1]) continue
let left = j + 1, right = len - 1
while (left < right) {
let sum = nums[i] + nums[j] + nums[left] + nums[right]
if (sum < target) {
left++
continue
}
if (sum > target) {
right--
continue
}
res.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 res
};
感想
- 好难写,好崩溃。但是思路跟上一题还是一样的。
- 多练练吧,今天有点怠惰了。
- 时间复杂度:O(n3),从O(n4)降了一阶。