当前位置:首页 » C语言&C++

LeetCode刷题之第一题——TwoSum

2015-01-18 23:10 本站整理 浏览(6137)

LeetCode刷题之第一题——TwoSum,有需要的朋友可以参考下。

原题:

Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input:numbers={2, 7, 11, 15}, target=9
Output:index1=1, index2=2

翻译:

给定一个整数数组,找出其中两个数满足相加等于你指定的目标数字。

要求:这个函数twoSum必须要返回能够相加等于目标数字的两个数的索引,且index1必须要小于index2。请注意一点,你返回的结果(包括index1和index2)都不是基于0开始的。

你可以假设每一个输入肯定只有一个结果。

举例:

输入:numbers={2, 7, 11, 15}, target = 9

输出:index1 = 1, index2 = 2(不是基于0开始的)

leetcode目前支持的解决方案的编程语言为c++和java,后期会加上python,这里面它会提供一个固定的接口让你去完成,比如这一题里面你需要在它提供的函数里面写出函数体即可。

解决:

开始的时候我没有其他的想法,只是想单纯的实现,从实现角度上来说,肯定是直接两层循环就可以完成,时间复杂度为o(n^2),空间复杂度为o(1),代码如下:

class Solution {
 public:
     vector<int> twoSum(vector<int> &numbers, int target) {
         vector<int> result;
         for (int i = 0; i < numbers.size()-1; i++) {
             for (int j = i+1; j < numbers.size(); j++) {
                 if (numbers[i] + numbers[j]==target) {
                     result.push_back(i+1);
                     result.push_back(j+1);
                     return result;
                 }
             }
         }
         return result;
     }
 };

结果肯定没有问题,但是结局肯定也是在意料之中的,那就是当输入的数组很大的时候,耗费的时间就会很长,在提交代码的时候,leetcode oj会报time limit exceeded这样的错误。

从上面的两层循环来说,由于数组无序实际上没有可优化的点了,必须要转变思维观念来解决,我个人认为除去优化解决时间复杂度的一个很明显的替代方法那就是以空间换时间,对于查找这类问题来说,想减少时间复杂度的一个好办法那就是建立hash表,在这里使用map结构来完成,代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int> &numbers, int target) {
        vector<int> result;
        map<int, int> m;
        if (numbers.size() < 2)
            return result;
        for (int i = 0; i < numbers.size(); i++)
            m[numbers[i]] = i;

        map<int, int>::iterator it;
        for (int i = 0; i < numbers.size(); i++) {
            if ((it = m.find(target - numbers[i])) != m.end())
            {
                if (i == it->second) continue;
                result.push_back(i+1);
                result.push_back(it->second+1);
                return result;
            }
        }
        return result;
    }
};

这里面有个陷阱就是if (i == it->second) continue这句,当时没有想到这个,运行了以后报错了,什么原因呢?就是如果说,数组里面只有一个3,但是目标数是6,那你可能返回的结果是两个相同的索引了,肯定是错的,所以需要排除掉这种情况。

其他思路:

当时还想到另一种方法,但是没有实现,主要是因为感觉代码会写出来比较复杂,就简单把方案描述下:

1,首先同样分配一个数组空间,将数据拷贝

2,将拷贝的数组排序

3,对排序数组,建立两个查找“指针”,一个在数组头,一个在数组尾部,依次相加比较,如果大了,尾部向前进一位,如果小了,头部向后进一位,直至有相等的情况或者头部与尾部交叉的情况发生,返回结果。