找出一个数组中和为n的两个数
实现目标
- 一个递增的数组 [1,2,4,7,11,15] 和一个 n=15
- 数组中有两个数,和为 n。即 4+11=15
- 实现函数找出这两个数
实现思路
嵌套循环方式
- 找出一个数,然后遍历下一个数,求和,判断
- 时间复杂度是 O(n^2),不可用了
双指针思路
- 随便找两个数
- 如果和大于 n,则需要向前寻找 - 利用递增(有序)的特性
- 如果和小于 n,则需要向后查找 - 二分法
- 时间复杂度降低到 O(n),具体思路
- 定义 i 指向头,j 指向尾,求 arr[i]+arr[j]
- 如果大于 n,则 j 需要向前移动
- 如果小于 n,则 i 需要向后移动
代码实现
ts
/**
* @desc 找出一个数组中和为n的两个数
* @author lzw.
*/
// 嵌套循环
function twoNumberSum1(arr: number[], n: number): number[] {
const res: number[] = []
const length = arr.length
if (length === 0) return res
let flag = false // 是否得到结果
// O(n^2)
for (let i = 0; i < length - 1; i++) {
const n1 = arr[i]
for (let j = i + 1; j < length - 1; j++) {
const n2 = arr[j]
if (n1 + n2 === n) {
res.push(n1)
res.push(n2)
flag = true
break
}
}
if (flag) break
}
return res
}
// 双指针思路
function twoNumberSum2(arr: number[], n: number): number[] {
const res: number[] = []
const length = arr.length
if (length === 0) return res
let i = 0; // 头
let j = length - 1 // 尾
// O(n)
while (i < j) {
const n1 = arr[i]
const n2 = arr[j]
const sum = n1 + n2
if (sum > n) {
// 需要向前移动
j--
} else if (sum < n) {
// 需要向后移动
i++
} else {
res.push(n1)
res.push(n2)
break
}
}
return res
}
// 功能测试
const arr = [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 4, 7, 11, 15]
const n = 15
// console.log(twoNumberSum2(arr, n))
// console.log(twoNumberSum2([], n))
// console.log(twoNumberSum2([1, 2, 4, 7, 12, 15], n))
// 性能测试
console.time('twoNumberSum1')
for(let i=0;i<100*10000;i++){
twoNumberSum1(arr, n)
}
console.timeEnd('twoNumberSum1') // 204.293ms
console.time('twoNumberSum2')
for(let i=0;i<100*10000;i++){
twoNumberSum2(arr, n)
}
console.timeEnd('twoNumberSum2') // 49.095ms
性能测试
ts
console.time('twoNumberSum1');
for (let i = 0; i < 100 * 10000; i++) {
twoNumberSum1(arr, n);
}
console.timeEnd('twoNumberSum1'); // 204.293ms
console.time('twoNumberSum2');
for (let i = 0; i < 100 * 10000; i++) {
twoNumberSum2(arr, n);
}
console.timeEnd('twoNumberSum2'); // 49.095ms