N 数之和系列
两数之和
给定一个数组,一个 target,找到数组中所有两个数字之和为 target 的组合。这里为了后面 N 数之和做准备,不是返回一个组合。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| function twoSum(nums: number[], target: number): number[][] { nums.sorts((a, b) => a - b);
let left = 0; let right = nums.length - 1; const res = []; while (left < right) { const lVal = nums[left]; const rVal = nums[right]; if (lVal + rVal === target) { res.push([lVal, rVal]); while (nums[left] === lVal) left++; while (nums[right] === rVal) right--; } else if (lVal + rVal < target) { left++; } else { right--; } } return res; }
|
三数之和
有了两数之和,三数之和的计算就可以依赖现有的两数之和的函数,但是要稍微改造一下。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
function twoSum(nums: number[], target: number, start: number): number[][] { let left = start; let right = nums.length - 1; const res = []; while (left < right) { const lVal = nums[left]; const rVal = nums[right]; if (lVal + rVal === target) { res.push([lVal, rVal]); while (nums[left] === lVal) left++; while (nums[right] === rVal) right--; } else if (lVal + rVal < target) { left++; } else { right--; } } return res; }
function threeSum(nums: number[]): number[][] { if (nums.length < 3) return [];
nums.sort((a, b) => a - b); const res = []; for (let i = 0; i < nums.length; i++) { const newTarget = 0 - nums[i]; const newStart = i + 1; const temp = twoSum(nums, newTarget, newStart); for (let j = 0; j < temp.length; j++) { res.push([nums[i], ...temp[j]]); } while (nums[i] === nums[i + 1]) i++; }
return res; }
|
N 数之和
有了上面的例子,继而推演出 N 数之和的通用方法,也就有了思路。每次确定一个数字,最终只剩两个数字的时候,就是调用两数之和的时候。需要注意的是,常规的想法是 N 是几,就进行 N-1 层遍历。这里 N 是未知的。不过可以使用递归,来一层一层的减少 N
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
function twoSum(nums: number[], target: number, start: number): number[][] { let left = start; let right = nums.length - 1; const res = []; while (left < right) { const lVal = nums[left]; const rVal = nums[right]; if (lVal + rVal === target) { res.push([lVal, rVal]); while (nums[left] === lVal) left++; while (nums[right] === rVal) right--; } else if (lVal + rVal < target) { left++; } else { right--; } } return res; }
function nSum( nums: number[][], target: number, n: number, start: number, visited: number[], ans: number[][] = [] ): number[][] { if (n + start > nums.length) return [];
if (n === 2) { const temp = twoSum(nums, target, start); for (let i = 0; i < temp.length; i++) { ans.push([...visited, ...temp[i]]); } return; } else { for (let i = start; i < nums.length; i++) { const newTarget = target - nums[i]; const newN = n - 1; const newStart = i + 1; const newVisited = [...visited, nums[i]]; nSum(nums, newTarget, newN, newStart, newVisited, ans); while (nums[i] === nums[i + 1]) i++; } } return ans; }
function fourSum(nums: number[], target: number): number[][] { nums.sort((a, b) => a - b); return nSum(nums, target, 4, 0, []); }
|