Leetcode第1题: 两数之和的三种解法

一、题目来源:leetcode第一题

二、题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 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]

提示:

  • 2 <= nums.length <= 10(4)
  • -10(9) <= nums[i] <= 10(9)
  • -10(9) <= target <= 10(9)
  • 只会存在一个有效答案

进阶: 你可以想出一个时间复杂度小于 O(n^2) 的算法吗?

三、解题

3.1 解法一

  1. 思路

两层for循环遍历,直到找到和为目标值 target 的那两个整数,并返回它们的数组下标。

  1. 解法

const twoSum = function ( nums, target ) {
    for ( let i = 0 ; i < nums. length ; i++) {
        for ( let j = i + 1 ; j < nums. length ; j++) {
            if (nums[i] + nums[j] === target) {
                return [i, j];
            } 
        }
    }
}; 
  1. 时间复杂度

该方法使用了两层嵌套的循环。外层循环从0到nums.length-1遍历数组中的每个元素,内层循环从外层循环的下一个元素开始遍历到数组的最后一个元素。因此,外层循环执行nums.length次,内层循环执行(nums.length-1) + (nums.length-2) + ... + 1次。在最坏情况下,内层循环的总执行次数约为(nums.length2)/2。因此,该方法的时间复杂度为**O(n2)** ,其中n是数组 nums 的长度。

  1. 空间复杂度

该方法只使用了常数级别的额外空间,即只创建了一个常数大小的数组来存储结果。因此,该方法的空间复杂度为O(1)

3.2 解法二

  1. 思路

我们可以先对 nums 排序,然后利用左右双指针,从两端相向而行找到和为目标值 target 的那两个整数,并返回在原始数组中它们的数组下标。

  1. 解法

const twoSum = function ( nums, target ) {  
    for ( let i = 0 ; i < nums. length ; i++) { 
        for ( let j = i + 1 ; j < nums. length ; j++) { 
            if (nums[i] + nums[j] === target) {
                return [i, j];
            }
        } 
    } 
}; 
  1. 时间复杂度

  • 复制数组:oringinalNums = [...nums]这一步需要遍历整个数组,因此时间复杂度为O(n),其中n为数组nums的长度。
  • 排序数组:nums.sort((a, b) => a - b)这一步使用快速排序算法,其平均时间复杂度为O(nlogn)。
  • 双指针移动:在while循环中,左指针和右指针进行移动,最多移动n次(即数组的长度),因此时间复杂度为O(n)。
  • 综上所述,该方法的时间复杂度为O(nlogn)
  1. 空间复杂度

在算法中创建了一个新的数组oringinalNums来保存原始的nums,其长度与nums相同,因此需要O(n)的额外空间。其他变量的空间使用是常数级别的,不随输入规模变化,因此可以忽略。因此,总体空间复杂度为O(n)

3.3 解法三

  1. 思路

对于一个元素 nums[i],你想知道有没有另一个元素 nums[j] 的值为 target - nums[i],可以用一个哈希表记录每个元素的值到索引的映射,这样就能快速判断数组中是否有一个值为 target - nums[i] 的元素了。

  1. 解法

const twoSum = function ( nums, target ) {
    // 维护 val -> index 的映射
    const valToIndex = new  Map ();
    for ( let i = 0 ; i < nums. length ; i++) {
        // 查表,看看是否有能和 nums[i] 凑出 target 的元素
        const need = target - nums[i];
        if (valToIndex. has (need)) {
            return [valToIndex. get (need), i];
        }
        // 存入 val -> index 的映射
        valToIndex. set (nums[i], i);
    }
    return  null ;
};
  1. 时间复杂度

  • 创建映射表:在for循环之前,通过const valToIndex = new Map()创建了一个空的Map对象。这一步的时间复杂度是O(1)。
  • 遍历数组并查找映射表:在for循环中,遍历了整个数组,并且对于每个元素,通过valToIndex.has(need)进行查找,其中need是目标值与当前元素的差。Map查找的时间复杂度是O(1)。因此,整个遍历过程的时间复杂度是O(n),其中n为数组nums的长度。
  • 综上所述,该方法的时间复杂度为O(n)
  1. 空间复杂度

该方法使用了一个映射表valToIndex来存储元素值和索引的映射关系。在最坏的情况下,映射表需要存储整个数组的所有元素,因此空间复杂度为O(n) ,其中n为数组nums的长度。

四、知识点

常见时间复杂度,按照增长速率从小到大进行排序:

  1. O(1):常数时间复杂度,表示算法的执行时间是一个常数,不随输入规模的增加而改变。例如,访问数组中的某个元素、进行固定次数的循环等。
  2. O(log n):对数时间复杂度,表示算法的执行时间与输入规模的对数成正比。常见的具有对数时间复杂度的算法有二分查找、平衡二叉树的插入和删除操作等。
  3. O(sqrt(n)):平方根时间复杂度,表示算法的执行时间与输入规模的平方根成正比。例如,求解素数的方法中的试除法。
  4. O(n):线性时间复杂度,表示算法的执行时间与输入规模成线性关系。例如,遍历数组、查找最大值或最小值等。
  5. O(n log n):线性对数时间复杂度,表示算法的执行时间与输入规模的乘积与对数的乘积成正比。常见的具有线性对数时间复杂度的算法有快速排序、归并排序等。
  6. O(n^2):平方时间复杂度,表示算法的执行时间与输入规模的平方成正比。例如,嵌套循环遍历二维数组、冒泡排序等。
  7. O(2^n):指数时间复杂度,表示算法的执行时间随着输入规模的增加呈指数级增长。例如,求解斐波那契数列的递归算法。
  8. O(n!):阶乘时间复杂度,表示算法的执行时间随着输入规模的增加呈阶乘级增长。例如,求解旅行商问题的穷举算法。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352