码迷,mamicode.com
首页 > Web开发 > 详细

JS leetcode 两数之和解答思路分析

时间:2020-05-13 00:33:41      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:jpg   htm   pre   跳过   val   思路分析   image   mic   不能   

技术图片

壹 ? 引

在学习算法基础的同时,我还是继续捡起leetcode的算法题了,珍惜时间,算法每天进步一点点。不得不说,在了解了一些算法概念后,至少有些答案是能看懂了......(惭愧)虽然我很菜,但是多写多练应该还是会有提升。那么这篇文章就从两数之和开始。

原题如下:

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

请实现如下方法能达到上述效果:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {

};

贰 ? 听风是风不太聪明的实现

在解释优质答案前,我先说说自己的思路,毕竟不是很好的做法,大家也可以跳过不看。

我想出了两种做法,先说第一种,由于只有一个数组,但是我们得让数组中的元素两两相加并与目标值判断是否相等,所以首先想到就是利用for循环嵌套,遍历同一个数组。

技术图片

由于不能重复使用同一个元素,所以外层从0开始遍历时,内层循环的索引起点肯定得是1,当外层是1时,内层索引从2开始。这样做的目的除了避免同一元素多次使用外,还减少了重复比较次数。我们来大致脑补下,比如外层是0时,会与内层1相加,而如果内层不在外层基础上加1,就还会出现外层是1时,与内层是0相加比较的情况,这样就重复了。

技术图片

所以知道了这些就好做了,直接贴我的实现:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function (nums, target) {
    // 用来装目标索引的空数组
    var result = [],
        len = nums.length;
    for (var i = 0; i < len; i++) {
        // 注意,这里从i+1开始遍历
        for (var j = i + 1; j < len; j++) {
            if (nums[i] + nums[j] === target) {
                // 注意,concat返回一个新数组
                result = result.concat(i, j);
                return result;
            };
        };
    }
};

我想到的第二种解决思路其实是在学插入排序时得到的灵感,上面的实现简单粗暴,无非就是把一个数组当两个用,第二种思路就是对同一个数组正序倒序同时遍历比较,当然也得使用循环嵌套。

比如外层循环从0开始,那么内层循环从length-1处倒序遍历,一直遍历到0前面一位,期间的元素分别与0的数字相加并与target比较:

技术图片
技术图片

直接贴我的第二种思路,由于还是使用了循环嵌套,所以耗时相比第一种也只是提升了一点点,但内存使用却大了不少,所以也不算很好的实现。

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function (nums, target) {
    var result = [],
        len = nums.length;
    for (var i = 0; i < len; i++) {
        var len_ = len - 1;
        // 倒序遍历,一直遍历到i的前一位
        while (len_ > i) {
            if (nums[i] + nums[len_] === target) {
                result = result.concat(i, len_);
                return result;
            };
            len_--;
        };
    };
};

叁 ? 优质解答

那么在说完我的弱智算法,来看看官方的优质解答,直接贴代码,我们再分析实现:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function (nums, target) {
    var temp = [],
        len = nums.length;
    for (var i = 0; i < len; i++) {
        var dif = target - nums[i];
        if (temp[dif] != undefined) {
            return [temp[dif], i];
        };
        temp[nums[i]] = i;
    };
};

这个思路其实就是借助了哈希表,牺牲少量空间大大减少运行用时,毕竟只用了一次遍历。如果大家对于哈希表很陌生,还是很推荐大家先理解常用数据结构,我在从零开始的算法入门科普(二)一文中有通过图解简单科普哈希表的概念,只是在上述代码在哈希表存值时并未借助哈希函数。

通常来说哈希表常常用来存储key-value的数据,由于我们最终是要获取目标元素索引,所以代码实现中直接使用数组元素作为位置映射,用于存储当前元素索引。其次,巧妙通过var dif = target - nums[i]分别获取目标值与当前遍历元素的差值,如果这个差值作为哈希表的索引能访问到有效元素,那么说明当前遍历的i与temp[dif](拿到的是元素在nums中的索引)就是要找的索引。

不看答案我是真的想不上去,表示惊呆了,那么关于两数之和就说到这了,收获很大!!!

本文结束!

JS leetcode 两数之和解答思路分析

标签:jpg   htm   pre   跳过   val   思路分析   image   mic   不能   

原文地址:https://www.cnblogs.com/echolun/p/12877981.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!