1.题目描述

给定一个整数数组nums和一个目标值target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。

可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:
给定nums=[2,7,11,15],target=9**
因为nums[0]+nums[1]=2+7=9**
所以返回[0,1]**

2.题目分析

Ⅰ.暴力解法

暴力解法思路其实很简单,遍历数组中的每一个元素,寻找数组中是否存在另一个元素,使该两个元素之和等于target的值。很明显,该算法需要两层循环,时间复杂度为O(n^2).

Ⅱ.哈希表法

首先简单介绍一下什么是哈希表:

哈希表是一种常用的数据结构,它利用的是数组支持按照下标随机访问数据的特性,所以哈希表其实就是数组的一种扩展,由数组演化而来。哈希表具有数组的随机读取特性,读取一个元素的时间复杂度通常情况下为O(1).

假如我们考虑一个一维数组,为了找到数组中的某个元素,你可以依次遍历整个数组,比如线性查找(也可以二分查找),但是对于一个元素很多的数组来说,如果运气不好的话,那将会花费大量的时间。

现在假设你想要读取数组中的某个元素,而你正好知道它的下标值(index),那么你可以迅速地找到你所要查询的元素。因此,如果你知道数组里每个元素的索引值,你查找它所需的时间复杂度就与数组的大小以及元素位置都无关了。

但是你要怎么知道哪个索引值里的元素是你想要查找的呢?

哈希表就提供了这样一个办法,它将每一个索引值和它所在处元素之间建立了某种对应的关系。换句话说,你想要查找某元素,可以通过某种计算得到其索引值,再通过索引值就可以找到它了。

继续上面的例子,如果我们将在数组里连续存储了多个名字。我们可以将名字的每个字母用ASCII码表示,并把它们相加,因为我们现在数组中有11个元素,所以我们取各字母ASCII码和与元素个数的余数作为我们即将放入元素的位置。

这种将元素映射到数组下标的方法我们称之为哈希函数。

这样一来,我们就建立了每个名字和其索引值之间的关系。这时如果我们要查找某个元素,通过我们的哈希函数就可以得到其索引值,进而就可以进行随机访问了。

回到我们的问题,由于题目最终要求我们返回的值是元素的下标。如果我们想要知道一个元素的下标,最基本的办法就是对数组进行遍历,直到找到一个索引值,其对应元素为我们的目标。

如果采用哈希表,我们希望返回值为元素下标。同时由于数组中元素均为整数,为了方便,我们可以直接将将元素值作为哈希表的索引值,哈希表中每个索引值对应着该元素的下标。于是我们可以遍历每个元素,用target减去该元素,得到我们需要查找的目标值。如果该元素存在哈希表中,我们就可以直接返回当前数组索引值和哈希表中目标值所对应其索引值。利用该算法,所需时间复杂度为O(n)

3.手绘讲解

4.代码实现

#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;

vector<int> twoSum(vector<int>&, int);
int main()
{
    vector<int> nums = { 0, 1, 4, 5, 8, 10 };
    vector<int> ans = twoSum(nums, 13);
    for (auto x : ans)
        cout << x << endl;
    return 0;
}

vector<int> twoSum(vector<int>& nums, int target) {
    unordered_map<int, int> hash;
    for (int i = 0; i < nums.size(); ++i)
    {
        if (hash.find(target - nums[i]) != hash.end())
            return { hash[target - nums[i]],i };
        else
            hash[nums[i]] = i;
    }
    return {};
}

5.高票回答

C++实现:

vector<int> twoSum(vector<int> &numbers, int target)
{
    //Key is the number and value is its index in the vector.
    unordered_map<int, int> hash;
    vector<int> result;
    for (int i = 0; i < numbers.size(); i++) {
        int numberToFind = target - numbers[i];

            //if numberToFind is found in map, return them
        if (hash.find(numberToFind) != hash.end()) {
                    //+1 because indices are NOT zero based
            result.push_back(hash[numberToFind] + 1);
            result.push_back(i + 1);            
            return result;
        }

            //number was not found. Put it in the map.
        hash[numbers[i]] = i;
    }
    return result;
}

Java实现:

public int[] twoSum(int[] numbers, int target) {
    int[] result = new int[2];
    Map<Integer, Integer> map = new HashMap<Integer, Integer>();
    for (int i = 0; i < numbers.length; i++) {
        if (map.containsKey(target - numbers[i])) {
            result[1] = i;
            result[0] = map.get(target - numbers[i]);
            return result;
        }
        map.put(numbers[i], i);
    }
    return result;
}

Python实现

class Solution(object):
    def twoSum(self, nums, target):
        if len(nums) <= 1:
            return False
        buff_dict = {}
        for i in range(len(nums)):
            if nums[i] in buff_dict:
                return [buff_dict[nums[i]], i]
            else:
                buff_dict[target - nums[i]] = i

欢迎扫描下方二维码关注我的公众号《小R在编程》了解更多LeetCode题解思路和有计算机相关知识!

二维码.jpg


Roger
7 声望2 粉丝