【两根指针——Two Sum系列问题】Lintcode 56. 两数之和

Lintcode 56. 两数之和

题目描述:给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。
你需要实现的函数twoSum需要返回这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 0 到 n-1。

  • 你可以假设只有一组答案。

在这里插入图片描述
这道题之在leetcode中也做过(【Leetcode热题100】Leetcode 1. 两数之和),当时用的是二分法,时间复杂度O(nlogn),空间复杂度O(n)。

这次用两根指针哈希表方法再分别实现一下,关于这二者复杂度如下:
两根指针:时间复杂度O(nlogn),空间复杂度O(n);
哈希表:时间复杂度O(n),空间复杂度O(n);

这样看上去哈希表更好,这是因为本题是返回索引值,索引值需要额外空间O(n),如果是直接返回值的话,那二者的复杂度哈希表不变,而两根指针变为:时间复杂度O(nlogn),空间复杂度O(1),因为两根指针是直接在原数组中进行比较寻找的(所以无额外空间),此外它本身的时间复杂度是O(n),是因为需要先对数组排序(O(nlogn))导致复杂度为O(nlogn)。

下面给出两根指针和哈希表两种方法的实现代码:

// 1. 两根指针
class Solution {
    
    
public:
    /**
     * @param numbers: An array of Integer
     * @param target: target = numbers[index1] + numbers[index2]
     * @return: [index1 + 1, index2 + 1] (index1 < index2)
     */
    vector<int> twoSum(vector<int> &numbers, int target) {
    
    
        vector<int> result;
        if (0 == numbers.size()) {
    
    
            return result;
        }
        
        vector<int> sortIdx(numbers.size());
        iota(sortIdx.begin(), sortIdx.end(), 0);//全部赋值为0
        sort(sortIdx.begin(), sortIdx.end(), [&numbers](int i1, int i2) {
    
    return numbers[i1] < numbers[i2];});//获得原数组排序之后的索引
        sort(numbers.begin(), numbers.end());//对原数组进行排序
        
        int left = 0, right = numbers.size() - 1;
        while (left < right) {
    
    
            if (numbers[left] + numbers[right] == target) {
    
    
                result.push_back(sortIdx[left] < sortIdx[right] ? sortIdx[left] : sortIdx[right]);
                result.push_back(sortIdx[left] > sortIdx[right] ? sortIdx[left] : sortIdx[right]);
                break;
            } else if (numbers[left] + numbers[right] > target) {
    
    
                right--;
            } else {
    
    
                left++;
            }
        }
        
        return result;
    }
};

// 2. 哈希表方法
class Solution {
    
    
public:
    /**
     * @param numbers: An array of Integer
     * @param target: target = numbers[index1] + numbers[index2]
     * @return: [index1 + 1, index2 + 1] (index1 < index2)
     */
    vector<int> twoSum(vector<int> &numbers, int target) {
    
    
        vector<int> result;
        if (0 == numbers.size()) {
    
    
            return result;
        }
        
        map<int, int> numsMap;//数值和索引的映射关系
        for (int i = 0; i < numbers.size(); ++i) {
    
    
            int other = target - numbers[i];
            if (numsMap.count(other)) {
    
    
                result.push_back(numsMap[other]);
                result.push_back(i);
            } else{
    
    
                numsMap[numbers[i]] = i;
            }
        }
        
        return result;
    }
};

猜你喜欢

转载自blog.csdn.net/phdongou/article/details/113846424
今日推荐