[LeetCode] 1. 两数之和

引言

对于程序员来说, 算法二字应该都不陌生!!

首先什么是 算法? 它是解决问题的一个思路, 至于使用什么语言去完成不是它的重点, 你可以使用 Java 也可以使用 JS 甚至可以是任何你所熟悉的语言!!

那么我们为什么要学习 算法 呢? 即便我们没研究过它, 我们不是照样一样能完成手头的工作嘛? 其实在工作中, 业务开发过程中, 我们肯定会遇到一个个问题, 并通过编码解决它, 这中间其实或多或少都会用到 算法 只是我们可能对 算法 没怎么研究, 所以并没有感知到!!!

那么学习 算法 到底能给我带来什么呢?

  1. 对于求职者而, 算法 能力能成为你拿到优质 offer 的敲门砖, 不管是大厂还是国外面试都要求有一定 算法 能力
  2. 算法 是解决某类问题的的思路, 通过它可以很好培养我们的逻辑思维能力
  3. 也行在平常工作中你用不到你所学的 算法, 但是当遇到一些复杂问题, 它可以帮助你在复杂的情况中更好地分析问题、解决问题、从而寻找出最优的解决问题的思路
  4. 让我们自己研究 算法 很难, 但是目前很多 算法 都是几代人努力, 研究出来的, 我们可以直接研究学习, 站在巨人的肩膀上成就自我, 何乐而不为呢
  5. 算法 是一种解决问题的思路和方法, 也行有机会应用到生活和事业的其他方面呢
  6. 长期来看, 大脑思考能力是个人最重要的核心竞争力, 而算法是为数不多的能够有效训练大脑思考能力的途径之一

所以相信我, 学习 算法 应该是一件很酷的事情, 所以这里我专门整了个专栏, 希望我能坚持下去吧....

一、题目介绍

地址: leetcode.cn/problems/tw...

  1. 描述:
  • 给定一个整数数组 nums 和一个目标整数 target
  • 请从数组 nums 中找出 两个 值, 它们的和为目标整数 target
  • 注意 📢 最终我们需要返回这两个值在数组中的下标
  1. 补充:
  • 只会存在一个有效答案, 也就是说你只需要找到一对数值就行
  • 数组中同一个元素在答案里不能重复出现
  • 可以按任意顺序返回答案
  1. 示例:
js 复制代码
示例 1: 
输入: nums = [2, 7, 11, 15], target = 9
输出: [0, 1]
解释: 因为 nums[0] + nums[1] == 9, 返回 [0, 1]

示例 2: 
输入: nums = [3, 2, 4], target = 6
输出: [1, 2]

示例 3: 
输入: nums = [3, 3], target = 6
输出: [0, 1]

下面开始做题....

二、 暴力破解

这里最简单做法就是, 直接对数组进行嵌套循环

  • 第一层循环, 遍历整个数组
  • 第二层循环, 遍历所有剩余的数据
  • 这时就能拿到两个值, 判断它们之和是否是等于目标值
  • 结束循环的条件是: 拿到的两个值等于目标值, 这时直接 return 出这两个值的索引, 从而结束循环
js 复制代码
const nums = [2, 7, 11, 15]
const target = 9

const twoSum = (nums = [], target = 0) => {
  for (let i = 0; i < nums.length; i ++) { // 第一层循环, 遍历整个数组
    for (let j = i + 1; j < nums.length; j ++ ) { // 第二层循环, 遍历所有剩余的数据

      // 判断, 两数之和是否等于 target, 如果是则结束循环
      if (nums[i] + nums[j] === target) {
        return [i, j]
      }
    }
  }
}

twoSum(nums, target)

最后运行时间为 60ms

整体时间复杂度为 O(n^2),

三、使用 JS 原生方法

其实这里思路本质上和上面那个方法是一样的, 只是这里将第二个循环的处理逻辑改用 JS 的原生方法来实现, 相对来说可能更好理解一点:

  • 首先先循环, 遍历整个数组
  • 然后每次循环, 都尝试使用 indexOf 从剩余的数据中找到一个, 和 当前值 相加能够等于 目标值 的数据, 当然 indexOf 最终拿到的是对应值的索引, 刚好符合我们的要求(因为这里我们也只是需要值的索引)
  • 结束循环的条件是: 找到和 当前值 相加等于 目标值 的索引
js 复制代码
const nums = [2, 7, 11, 15]
const target = 9

const twoSum = (nums = [], target = 0) => {
  for (let i = 0; i < nums.length; i ++) { // 首先先循环, 遍历整个数组
    // 尝试从剩余的数据中找到一个, 和 `当前值` 相加能够等于 `目标值` 的数据(拿到的是索引值)
    const nextIndex = nums.indexOf(target - nums[i], i + 1) 

    // 如果找到, 则结束循环
    if (nextIndex !== -1) {
      return [i, nextIndex]
    }
  }
}

twoSum(nums, target)

最后运行时间为 60ms

时间复杂度还是 O(n^2)

四、进阶(一次循环)

上面两种方法从时间复杂度上来看都是 O(n^2), 下面我们尝试只进行一次循环来解决我们的问题!

这里思路其实也简单, 就是通过空间来换取时间, 所谓空间可以理解为内存空间, 就是用一个数据, 可以是对象可以是 map 也可以是任何数据结构的数据, 来记录数据, 从而减少我们循环的次数(代码运行时间)。

那么这里我们解决思路就是:

  • 遍历循环整个数组
  • 在最开始创建一个 map 用于记录遍历过的数据, mapkey 是数组中的 数值, value 则是我们需要的 索引
  • 那么在每次循环时, 我们就可以使用 map 来查找, 和 当前值 相加等于 目标值 的数字是否出现过, 如果出现过就直接拿到它的索引和当前值的索引进行返回
  • 结束循环的条件是: map 中存在某个值, 和当前循环的值相加等于 目标值
js 复制代码
const nums = [2, 7, 11, 15]
const target = 9


const twoSum = (nums = [], target = 0) => {
  const map = new Map()                 // 用于记录遍历过的数据, key 是数组中的数值, value 则是我们需要的索引

  for (let i = 0; i < nums.length; i ++) { // 循环数组
    const targetNum = target - nums[i]     // 目标数字: 和当前数值相等能够等于 target 的值

    if (map.has(targetNum)) {              // 判断之前存的值是否有目标数值
      return [map.get(targetNum), i]       // 有则返回索引
    }

    map.set(nums[i], i)                    // 没有, 则将当前值作为 key, 索引作为值存到 map 中
  }
}

twoSum(nums, target)

最后运行时间为 62ms

时间复杂度 O(n)

相关推荐
妮妮喔妮25 分钟前
图片上传 el+node后端+数据库
javascript·数据库·vue.js
霜绛26 分钟前
机器学习笔记(四)——聚类算法KNN、Kmeans、Dbscan
笔记·算法·机器学习·kmeans·聚类
晨非辰1 小时前
#C语言——学习攻略:深挖指针路线(三)--数组与指针的结合、冒泡排序
c语言·开发语言·数据结构·学习·算法·排序算法·visual studio
zzywxc7871 小时前
编程算法在金融、医疗、教育、制造业等领域的落地案例
人工智能·算法·金融·自动化·copilot·ai编程
zzywxc7871 小时前
编程算法在金融、医疗、教育、制造业的落地应用。
人工智能·深度学习·算法·机器学习·金融·架构·开源
conkl2 小时前
构建 P2P 网络与分布式下载系统:从底层原理到安装和功能实现
linux·运维·网络·分布式·网络协议·算法·p2p
Shan12052 小时前
递归算法的一些具体应用
算法
求知若渴,虚心若愚。3 小时前
Error reading config file (/home/ansible.cfg): ‘ACTION_WARNINGS(default) = True
linux·前端·ansible
LinDaiuuj4 小时前
最新的前端技术和趋势(2025)
前端
paopaokaka_luck4 小时前
婚纱摄影管理系统(发送邮箱、腾讯地图API、物流API、webSocket实时聊天、协同过滤算法、Echarts图形化分析)
vue.js·spring boot·后端·websocket·算法·echarts