• 8、在一个数组中找出和为n的两个数


    在一个数组中找出和为n的两个数

    • 有一个递增的数组[1,2,4,7,11,15]和一个n=15
    • 数组中有两个数,和是n。即4 + 11 === 15
    • 写一个JS函数,找出这两个数

    常规思路

    • 嵌套循环,找到一个数,然后去遍历下一个数,求和,判断
    • 时间复杂度是O(n^2), 不可用

    代码实现——嵌套循环

    function searchNum1 (arr:number[],n:number):number[] {
      const len = arr.length
      if (len < 2) return [];
      const res:number[] = []
      
      for (let i = 0; i < len; i++) {
        let flag = false // 判断是否找到了结果
        for (let j = i + 1; j < len; j++) {
          let sum = arr[i] + arr[j]
          if (sum === n ) {
            flag = true
            res.push(arr[i])
            res.push(arr[j])
            break;
          } 
        }
        if (flag) break; 
      }
      return res
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    功能测试——嵌套循环

    const arr = [1,2,4,7,11,15]
    
    console.log(searchNum1(arr,15)) // [4, 11]
    
    • 1
    • 2
    • 3

    单元测试——嵌套循环

    describe('查找两数之和',() => {
      it('正常情况', () => {
        const arr = [1,2,4,7,11,15]
        const res = searchNum1(arr,15)
        expect(res).toEqual([4,11])
      })
    
      it('空数组', () => {
        const res = searchNum1([],15)
        expect(res).toEqual([])
      })
    
      it('找不到值的情况', () => {
        const arr = [1,2,4,7,11,15]
        const res = searchNum1(arr,100)
        expect(res).toEqual([])
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    利用递增有序的特性找出优化方法

    • 随便找两个数
    • 如果和大于n,则需要向前寻找
    • 如果和小于n,则需要向后寻找——二分法思想

    使用双指针,时间复杂度降低到O(n)

    • 定义i指向头,j指向尾,求arr[i] + arr[j]
    • 如果大于n,则需要向前移动
    • 如果小于n,则需要向后移动

    代码实现——双指针

    function searchNum2 (arr:number[],n:number):number[] {
      const len:number = arr.length
      if (len < 2) return []
    
      const res:number[] = []
    
      let i = 0 // head
      let j = len -1 // tail
    
      while(i < j) {
        let sum = arr[i] + arr[j]
        if (sum > n) {
          // 和大于n,则向前找,尾部下标-1
          j--;
        } else if (sum < n) {
          // 和小于n,则向后找,头部+1
          i++;
        } else {
          // 相等
          res.push(arr[i])
          res.push(arr[j])
          break;
        }
      }
        
      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

    功能测试——双指针

    const arr = [1,2,4,7,11,15,18,19,20]
    
    console.log(searchNum2(arr,15)) // [4,11]
    
    • 1
    • 2
    • 3

    单元测试——双指针

    describe('查找两数之和',() => {
      it('正常情况', () => {
        const arr = [1,2,4,7,11,15]
        const res = searchNum2(arr,15)
        expect(res).toEqual([4,11])
      })
    
      it('空数组', () => {
        const res = searchNum2([],15)
        expect(res).toEqual([])
      })
    
      it('找不到值的情况', () => {
        const arr = [1,2,4,7,11,15]
        const res = searchNum2(arr,100)
        expect(res).toEqual([])
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    性能比较——嵌套循环VS双指针

    const arr = [1,2,1,2,1,2,1,2,1,2,1,2,4,7,11,15,18,19,20]
    
    console.time('searchNum1')
    for (let i = 0; i < 100 * 10000; i++) {
      searchNum1(arr,15)
    }
    console.timeEnd('searchNum1')
    
    console.time('searchNum2')
    for (let i = 0; i < 100 * 10000; i++) {
      searchNum2(arr,15)
    }
    console.timeEnd('searchNum2')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    打印结果:

    searchNum1: 133.034ms
    searchNum2: 38.977ms
    
    • 1
    • 2

    时间复杂度:嵌套循环O(n^2) ,双指针O(n)

    综上所述,双指针用于解决此题更优

    总结

    • 时间复杂度达到O(n^2),是不可用的算法
    • 凡是有序,都可以考虑二分法思想
    • 优化嵌套循环,可以考虑“双指针 ”
  • 相关阅读:
    net-java-php-python-医药库存管理系统计算机毕业设计程序
    前端实现下载文件(处理后端返回的二进制流)
    我们不一样①
    代码随想录算法训练营第29天(贪心)|455.分发饼干、376. 摆动序列、53. 最大子序和
    C++ 之 perf+火焰图分析与Debug
    【JS】使用wavesurfer播放网络音频(Vue)
    C++单例模板:使用宏函数实现
    学会 Arthas,让你 3 年经验掌握 5 年功力
    在条码软件中如何制作ISBT-128条码
    Flask1.1.4 Werkzeug1.0.1 源码分析:启动流程
  • 原文地址:https://blog.csdn.net/qq_36362721/article/details/127637528