[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)

相关推荐
理想不理想v20 分钟前
vue经典前端面试题
前端·javascript·vue.js
不收藏找不到我21 分钟前
浏览器交互事件汇总
前端·交互
小阮的学习笔记34 分钟前
Vue3中使用LogicFlow实现简单流程图
javascript·vue.js·流程图
YBN娜35 分钟前
Vue实现登录功能
前端·javascript·vue.js
阳光开朗大男孩 = ̄ω ̄=35 分钟前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
幸运超级加倍~37 分钟前
软件设计师-上午题-16 算法(4-5分)
笔记·算法
minDuck40 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
yannan2019031344 分钟前
【算法】(Python)动态规划
python·算法·动态规划
埃菲尔铁塔_CV算法1 小时前
人工智能图像算法:开启视觉新时代的钥匙
人工智能·算法
EasyCVR1 小时前
EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?
人工智能·算法·ffmpeg·音视频·webrtc·监控视频接入