给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
方法一:暴力法
遍历每个元素x,查找是否存在一个值与target-x相等的目标元素。
时间复杂度:对每个元素都试图遍历数组的其余部分来寻找它所对应的目标元素,这将耗费O(n)的时间,n个元素所以时间复杂度是O(n2)。
空间复杂度:O(1)。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0;i<nums.size();i++){
for(int j=i+1;j<nums.size();j++){
if(nums[i]+nums[j]==target)
return vector<int>{i,j};
}
}
return vector<int>{};
}
};
方法二:两遍哈希表
第一次迭代:将每个元素的值和它的索引添加到表中。
第二次迭代:检查每个元素对应的目标元素(target-nums[i])是否存在于表中。
时间复杂度:遍历两次包含n个元素的列表,哈希表的查找时间是O(1),所以时间复杂度是O(n)。
空间复杂度:所需的额外空间取决于哈希表中存储的元素数量,该表中存储了n个元素,所以空间复杂度是O(n)。
class Solution{
public:
vector<int> twoSum(vector<int>& nums, int target){
map<int,int> hash;
for(int i=0;i<nums.size();i++)
hash[nums[i]]=i;
for(int i=0;i<nums.size();i++){
int t=target-nums[i];
//用find函数来定位数据出现位置,它返回的是一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器
if(hash.find(t)!=hash.end()&&hash[t]!=i)//不能重复利用这个数组中同样的元素
return vector<int>{i,hash.find(t)->second};//first访问map的第一个元素key,second访问第二个元素value
}
return vector<int>();
}
};
方法三:一遍哈希表
在第一遍遍历元素插入到表中之前,先检查表中是否已经存在当前元素对应的目标元素,如果已经存在,即找到了对应解,将其返回,如果不存在,将当前元素插入到表中继续对下一个元素进行操作。
时间复杂度:遍历包含n个元素的列表一次,哈希表每次查找花费O(1)的时间,因此时间复杂度是O(n)。
空间复杂度:所需的额外空间取决于哈希表中存储的元素数量,该表最多需要存储n个元素,所以空间复杂度是O(n)。
class Solution{
public:
vector<int> twoSum(vector<int>& nums, int target){
map<int,int> hash;
for(int i=0;i<nums.size();i++){
int t= target-nums[i];
if(hash.find(t)!=hash.end())
return vector<int>{hash.find(t)->second,i}; //当前元素与之前插入表中的元素进行比对,所以哈希表中元素的索引在前,当前元素序号在后
hash[nums[i]]=i;
}
return vector<int> {};
}
};