Algorithme : trouver les deux nombres dans le tableau qui totalisent n - idée de double pointeur

sujet

Trouver deux nombres dont la somme est n dans le tableau (incrémentation), indépendamment de deux paires ou plus, par exemple :

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

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

train de pensée

Idée 1 :
Notre première pensée est de parcourir deux fois, et d'additionner les nombres des deux traversées pour voir si c'est la cible n, mais l'inconvénient est évident, la complexité temporelle des deux traversées est O(n^2), qui est impossible à récupérer.

Idée 2:
Utilisez l'idée des doubles pointeurs, utilisez deux pointeurs (i, j) pour pointer respectivement vers la tête et la queue du nombre,
lorsque la somme des deux nombres est supérieure à n, j se déplace vers la gauche
lorsque la somme des deux nombres est inférieure à n , i se déplace vers la droite
jusqu'à ce que les i et j dont la somme est n soient trouvés, et les deux nombres correspondants peuvent être trouvés.

le code

/**
 * 寻找和为 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
}

cas de test

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([])
    })
})

Résumer

L'idée des doubles pointeurs réduit la complexité temporelle de O(n^2) à O(n)

Lorsque vous rencontrez des boucles imbriquées, pensez aux doubles pointeurs

おすすめ

転載: blog.csdn.net/weixin_43972437/article/details/130135455