题目描述:
给定一个整数数组nums和一个目标值target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
(你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。)
- 示例:
给定nums = [2, 7, 11, 15],
target = 9因为nums[0] + nums[1] = 2 + 7 = 9
所以返回[0,1]
解法一:使用两次循环遍历给定的数组,使得在数组中找到两个数之和为目标的值:
- 暴力法:
- 使用C++
class Solution{
public:
vector<int> twoSum(vector<int>& nums, int target){
//已知nums和target值:
// 直接搜索数组,返回两个数组的下标
int i,j;
// 注意使用c++里面的size()函数,两层循环使用<号,否则会栈溢出,第一层是不能包含到最后一个元素的
for(i=0; i < nums.size()-1; i++){
for(j=i+1; j < nums.size(); j++){
if(nums[i]+nums[j] == target){
return {i,j};
}
}
}
return {i,j};
}
// C++里面定义类的时候最后需要加上分号
};
- C语言暴力法:(C语言解法有点问题:returnSize没有使用上)
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
// 已知数组nums,数组大小,目标值,返回值的大小
int i,j;
int *result = NULL;
// 同样道理,i是不能取到最后的一个元素的
for(i=0;i<numsSize-1;i++){
for(j=i+1;j<numsSize;j++){
if(nums[i]+nums[j]==target){
// 当计算出来两个字和目标值相等之后,分配出两个int空间存放i和j,并返回result
result = (int*)malloc(sizeof(int)*2);
result[0]=i;
result[1]=j;
return result;
}
}
}
return result;
}
注:1、malloc是C语言中的动态内存分配,result=(int*)malloc(sizeof(int)2);malloc函数返回的类型是void型,所以需要强制类型转换成int,在前面加上(int*),才能给整形赋值,后面的(sizeof(int)*2)的意思是分配两个内存大小为int的空间;
总结该方法简单,但是使用的时间复杂度是O(n2),空间复杂度是O(1);运行速度慢而且内存空间消耗大
- 两遍哈希表:
- C++:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
// 两遍哈希表
map<int,int> a;//建立hash表存放数组的元素
vector<int> b(2,-1); //存放结果
for(int i=0;i<nums.size();i++)
a.insert(map<int,int>::value_type(nums[i],i));
for(int i=0;i<nums.size();i++){
if(a.count(target-nums[i])>0&&(a[target-nums[i]]!=i)){
//判断是否找到目标元素且目标元素不能是本身
b[0]=i;
b[1]=a[target-nums[i]];
break;
}
}
return b;
};
};
注:1.该方法使用map实现,map是STL的一个关联容器,它提供一对一(其中一个可以成为关键字,每个关键字只能在Map中出现一次,第二个可能称为该关键字的值)的数据处理能力。
- 一遍哈希表
- C++
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//一遍哈希表:
map<int,int> a; //提供一对一的hash
vector<int> b(2,-1); //用来承载结果,初始化一个大小为2,值为-1的容器b
for(int i=0;i<nums.size();i++){
if(a.count(target-nums[i])>0){
b[0]=a[target-nums[i]]; // 就是将差值放入到b[0]中
b[1]=i;
break;
}
a[nums[i]]=i; //反过来放入map中,用来获取结果下标
}
return b;
};
};
- Python3 暴力解法
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
size = len(nums)
for i,m in enumerate(nums):
j = i+1 # j的值必须从下一个开始啊
while j < size:
# 判断目标值是否等于m + n
if target == (m + nums[j]):
return [i,j]
else:
# print(i,j, m+_n,"didn't match!")
j += 1
对于给定的target,遍历数组时间复杂度O(n), 查找target == m + n的元素,时间复杂度O(n),因为时间复杂度为O(n^2),遍历的过程未使用数据结构存储,故空间复杂度为O(1)消耗费时间60ms
- 使用字典模拟hash
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
_dict = {}
# 首先是i与m对应进行逐个枚举遍历
for i,m in enumerate(nums):
_dict[m] = i
for i, m in enumerate(nums):
# 目标值减去其中的一个值m,剩下的就是差值
j = _dict.get(target - m)
# j存在,而且与j不等,则返回
if j is not None and i != j:
return [i, j]
- 一遍字典模拟Hash
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
_dict = {}
for i,m in enumerate(nums):
if _dict.get(target - m) is not None:
return [i, _dict.get(target - m)]
_dict[m] = i
- 其实使用一遍字典模拟Hash的时候只是将上面的字典模拟Hash简化,时间复杂度和空间复杂度都为O(n)。