leetcode01 TwoSum 两数之和 javascript解题

本题连接 leetcode-cn.com/problems/tw…算法

暴力法(两层循环)

看到这道题的第一反应就是,挺简单的,遍历两遍数组就能解决,咱们尝试一下。数组

let twoSum1 = 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]
            }
        }
    }
}
复制代码

的确解决了,但时间复杂度为o(n^2),最终经过时间为204ms,很不推荐,咱们能不能缩短期呢?bash

一层循环

咱们假设最终找到的两个值一个是x,一个是y,x + y = target,也就等价于 y = target - x。咱们只须要操做x就能解决这道题。思路是,判断target - x 这个值是否存在于这个数组中并与x的数组下标不相等。ui

let twoSum2 = function (nums, target) {
    for (let i = 0; i < nums.length; i++) {
        if (nums.indexOf(target - nums[i]) > -1 && nums.indexOf(target - nums[i]) !== i) { // 排除两个值相等的状况
            return [i, nums.indexOf(target - nums[i])];
            break; // 防止最终结果的下标出现两次
        }
    }
}
复制代码

最终顺利经过,但最后的时间为208ms,为何一层循环和两层循环的经过时间这么接近呢?由于twoSum2虽然只用了一层循环,但用到了js内置的方法indexOf(),这里面也有一层循环,其实最终仍是两层循环,这个方法也不推荐。spa

空间换时间,用对象把值存起来再操做

咱们用一个对象把数组里的下标和值都存起来,对象里的键表明数组的值,对象里的值表明数组下标,再用twoSum2里的思路去解题,这样只须要循环一次。code

let twoSum3 = function(nums,target){
    let obj = {};
    for(let i=0; i<nums.length; i++){
        obj[nums[i]] = i
    }
    for(let i=0; i<nums.length; i++){
        if(obj[target-nums[i]] && obj[target-nums[i]] !== i){
            return [i,obj[target-nums[i]]]
        }
    }
}
复制代码

这个方法时间复杂度为o(n),最终经过的时间是80ms,比以前快了两倍多,除了空间换时间,解题思路和twoSum2彻底同样。对象

用哈希表来解题

逛了下社区的解题,有不少同窗都用了哈希表来存值,最终实现空间换时间,下降时间复杂度。其实跟twoSum3的思路是同样的,咱们也试着用哈希表写一个。leetcode

let twoSum4 = function(nums, target) {
    const map = new Map()
    for(let i = 0; i < nums.length; i++){
        if (map.has(target - nums[i])){
            return [ map.get(target - nums[i]), i ]
        }
        map.set(nums[i], i)
    }
};
复制代码

最终经过时间84ms,跟twoSum3差很少。get

总结

本题最主要的思路就是用空间换时间,我的认为若是能很明显地减小时间复杂度,用空间换时间是值得的。反正无论怎样,写出来的算法时间复杂度是o(n^2)是很糟糕的,咱们必定要想尽办法,减小时间复杂度。io

相关文章
相关标签/搜索