Leetcode 编程训练[1]:Two Sum

#1: 题目要求是接收两个参数,一个数组参数存放整型数据,另一个参数为整型变量。我们需要找到两个数组内的数字,相加为整型参数,并返回这两个数字的位置。并且,给出的参数有且只有一个符合要求的组合。

首先,我想到的方法就是来用两个循环来历遍数组。代码如下:

/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]} two integers in an array, ie: [index1, index2]
 */
var twoSum = function(numbers, target) {
    var index1 = 0,
        index2 = 0;        
    //loop
    var length = numbers.length;
    for(var i = numbers.length; i--;){
        for(var j = i; j--;){
            if((numbers[i] >= numbers[j]) && (numbers[i] + numbers[j] == target)){
                index1 = i + 1;
                index2 = j + 1;
                break;
            }
        }        
    }        
    return [index1, index2];
};

满怀欣喜地提交代码,结果却是因为超时而未通过。原来这个方法的时间复杂度是O(n^2),系统的要求要减少复杂的。在网上搜答案,我的这种解法就叫蛮力法。更好的方法是通过哈希表得到时间复杂度是O(n)的方法,不过这种方法使得空间复杂度提高到了O(n)。很有意思。

这要怎么做的呢?我们看到内层循环其实只是在搜索匹配符合要求的情况,在搜索时外层标记变量i到来记录第一个加数的位置。我们可以把外层的记录放在哈希表上,将两次循环功能合并起来。

为什么使用哈希表这种数据结构了,因为我们需要使用哈希表的键值映射的特点。哈希表反过来着将每个元素数字所缺的加数target-numbers[i]作为哈希表的键(Key),而将整型元素所在下标存为所对应的值(Value)。这样在查找时,将第二个数字作为表的键来寻找,如果没有定义则将其作为新元素存储在表中。知道找到组合。

在coding的时候,犯了几个错误。首先,不知道在JS语言中,哈希表要怎么实现。搜索结果知道JS中对象就可以充当哈希表用,也就是JSON数据。二是map对象中没有数据的key存放的是undefined而不是null。

/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]} two integers in an array, ie: [index1, index2]
 */
var twoSum = function(numbers, target) { 
    //结果表    
    var result = [];    
    //映射表对象存储 key == number , value == position
    var map = {};
    //loop
    var length = numbers.length;
    for(var i = 0; i < length; i++){
        // 嵌套循环 o(n^2)复杂度 搜索
        // 需要使用映射表来减少收缩复杂度(o(n)->o(1))
        if(map[numbers[i]] === undefined){
            map[target- numbers[i]] = i;
        }else{
            result.push(map[numbers[i]] + 1);
            result.push(i + 1);
        }        
    }    
    return result;
};

最后运行的时间差不多160毫秒嘛,相比之下,c系果然是贴合性能王道。


Rescoure:
程序源码