算法:找出数组中和为n的两个数-双指针思想

题目

找出数组(递增)中和为 n 的两个数,不考虑两对及两对以上,例如:

const findTowNumbers = (arr, num) => {
    
    
	// ....
}

const arr = [1 ,2, 4, 7, 11, 15]
findTowNumbers(arr, 15)	// [4, 11]

思路

思路一:
我们首先想到的是,两次遍历,并将两次遍历的数字加起来看是不是目标 n,但是缺点很明显,两次遍历时间复杂度为 O(n^2),这是不可取的。

思路二:
使用双指针的思想,用两个指针(i、j)分别指向数的头部和尾部,
当两数之和大于 n 的时候,j 向左移动
当两数之和小于 n 的时候,i 向右移动
直到找到那个和为 n 的 i 和 j,就能找到对应的两个数了。

代码

/**
 * 寻找和为 n 的两个数(嵌套循环)
 * @param arr arr
 * @param n n
 */
export function findTowNumbers1(arr: number[], n: number): number[] {
    
    
    const res: number[] = []

    const length = arr.length
    if (length === 0) return res

    // O(n^2)
    for (let i = 0; i < length - 1; i++) {
    
    
        const n1 = arr[i]
        let flag = false // 是否得到了结果

        for (let j = i + 1; j < length; j++) {
    
    
            const n2 = arr[j]

            if (n1 + n2 === n) {
    
    
                res.push(n1)
                res.push(n2)
                flag = true
                break
            }
        }

        if (flag) break
    }

    return res
}
/**
 * 查找和为 n 的两个数(双指针)
 * @param arr arr
 * @param n n
 */
export function findTowNumbers2(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) {
    
    
            // sum 大于 n ,则 j 要向前移动
            j--
        } else if (sum < n) {
    
    
            // sum 小于 n ,则 i 要向后移动
            i++
        } else {
    
    
            // 相等
            res.push(n1)
            res.push(n2)
            break
        }
    }

    return res
}

测试用例

import {
    
     findTowNumbers2 } from './two-numbers-sum'

describe('两数之和', () => {
    
    
    it('正常情况', () => {
    
    
        const arr = [1, 2, 4, 7, 11, 15]
        const res = findTowNumbers2(arr, 15)
        expect(res).toEqual([4, 11])
    })

    it('空数组', () => {
    
    
        const res = findTowNumbers2([], 100)
        expect(res).toEqual([])
    })

    it('找不到结果', () => {
    
    
        const arr = [1, 2, 4, 7, 11, 15]
        const n = 100
        const res = findTowNumbers2(arr, n)
        expect(res).toEqual([])
    })
})

总结

双指针的思想,将时间复杂度从 O(n^2) 降为 O(n)

遇到嵌套循环的,就想想双指针

Guess you like

Origin blog.csdn.net/weixin_43972437/article/details/130135455