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 + n2if (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 - n4if (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 falseconst 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.lengthif (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]) continuewhile (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.lengthif (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]) continuefor (let j = i + 1; j < len - 2; j++){// 去重if (j > i + 1 && nums[j] === nums[j - 1]) continuelet left = j + 1, right = len - 1while (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)降了一阶。
