解法一:暴力解法

暴力解法的思路较为直接,在输入数组中分别对两个下标进行遍历,若满足题目要求,直接返回结果(题目中明确说明假设答案唯一)。

注意:

  1. 第一层循环应从0到n-2位置(n为数组长度),即不需要遍历到数组最后一个元素;
  2. 第二层循环应将第一层循环变量作为起点,遍历至数组最后一个元素。
  3. 下标从1开始,因此在保存结果时,要注意加1

代码如下:

class Solution {
public:
    /**
     * 
     * @param numbers int整型vector 
     * @param target int整型 
     * @return int整型vector
     */
    vector<int> twoSum(vector<int>& numbers, int target) {
        int n = numbers.size();
        vector<int> res;
        // 数组为空
        if (!n) 
            return res;
        // 两层循环 暴力求解
        for (int i = 0; i < n - 1; i ++) { // 从遍历至n-2位置
            for (int j = i + 1; j < n; j ++) { // 从i遍历至n-1位置
                if (numbers[i] + numbers[j] == target) {
                      // 下标从1开始
                    res.push_back(i + 1); 
                    res.push_back(j + 1);
                    return res;
                }
            }
        }
        return res;
    }
};

该方法采用两层循环遍历原数组,因此时间复杂度为平方级别,即O(N^2);该方法未定义额外空间(除保存结果所需要的数组外),因此空间复杂度为O(1)。

解法二:哈希表

上述方法的时间复杂度可以进一步优化至O(N)。

哈希表的思想为「以空间换时间」,这是由于哈希表保存了键值对,其「查找」复杂度为O(1)。

对于本题,具体解题思路为(如图所示):

  1. 定义哈希表hashmap,其存放的键值对为<取值,下标>。

  2. 从开始处遍历数组,对于第i个位置,在哈希表中寻找target-nums[i]是否存在,若存在,将两个下标放入数组中返回;若不存在,将其添加至表中,继续遍历。

图片说明

注:在将结果保存至数组中时,无需判断二者下标大小:当所遍历到的位置符合题目要求时,说明哈希表中已经存在待查找的另一元素,因此「已存在于表中的元素的下标」一定小于「当前位置元素的下标」。

代码实现如下:

class Solution {
public:
    /**
     * 
     * @param numbers int整型vector 
     * @param target int整型 
     * @return int整型vector
     */
    vector<int> twoSum(vector<int>& numbers, int target) {
        int n = numbers.size(); 
        vector <int> res;
        if (!n) 
            return res;
        // 定义哈希表,unordered_map是用哈希表实现的,复杂度为O(1),而map是用红黑树实现的
        unordered_map<int, int> hashmap; 

        for (int i = 0; i < n; i ++) {
            if (hashmap.find(target - numbers[i]) != hashmap.end()) { // find函数返回hashmap.end()代表未找到,否则代表找到
                // 将结果存入数组
                res.push_back(hashmap[target - numbers[i]] + 1); 
                res.push_back(i + 1);
                break;
            } else {
                hashmap[numbers[i]] = i; // 将未找到的值插入哈希表中,继续遍历
            }
        }
        return res;
    }
};

此解法只遍历数组一次,且在哈希表中查找的时间复杂度为O(1),因此总时间复杂度为O(N);该方法需要构建哈希表,因此空间复杂度为O(N)。