一、题目描述
题目所在的地址
给定一个整数数组 n u m s nums nums 和一个目标值 t a r g e t target target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 n u m s = [ 2 , 7 , 11 , 15 ] , t a r g e t = 9 nums = [2, 7, 11, 15], target = 9 nums=[2,7,11,15],target=9
因为 n u m s [ 0 ] + n u m s [ 1 ] = 2 + 7 = 9 nums[0] + nums[1] = 2 + 7 = 9 nums[0]+nums[1]=2+7=9
所以返回 [ 0 , 1 ] [0, 1] [0,1]
二、暴力法-两遍for循环
我的第一思路是双重for循环来遍历整个数组,遍历两次数组,当外循环下标和内循环下标对应的两个数相加为target时,退出循环。
1、c语言
#include<stdio.h>
#include<malloc.h>
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
int *ret = (int *)malloc(2*sizeof(int));
int temp;
for(int i = 0; i < numsSize - 1; i++){
temp = target - nums[i];
for(int j = i + 1; j < numsSize; j++){
if(temp == nums[j]){
*ret = i;
*(ret + 1) = j;
*returnSize = 2;
return ret;
}
}
}
return 0;
}
int main()
{
int *a = NULL;
int nums[4] = {2,7,11,15};
int* returnS;
a = twoSum(nums, 4, 9, returnS);
if(*returnS == 2)
printf("%d %d", a[0], a[1]);
free(a);
return 0;
}
知识点:
malloc 是c语言中的动态分配内存, int *ret = (int *)malloc(2*sizeof(int)); ,malloc函数返回的是void* 型,所以要强制类型转换成 int,在前面加上 (int *) , 才能给整型赋值,后面 (2*sizeof(int)) 的意思是分配两个 int 大小的空间。
2、c++语言
#include<iostream>
#include<vector>
using namespace std;
class Solution
{
public:
vector<int> twoSum(vector<int>& nums, int target)
{
vector<int> ans;
int temp;
for(int i = 0; i < nums.size()-1; i++)
{
temp = target - nums[i];
for(int j = i+1; j < nums.size(); j++)
{
if(temp == nums[j])
{
ans.push_back(i);
ans.push_back(j);
return ans;
}
}
}
return ans;
}
};
int main()
{
vector<int> nums = {2, 7, 11, 15};
vector<int> ans;
Solution solu;
ans = solu.twoSum(nums, 9);
cout << ans[0] << " " << ans[1] << endl;
return 0;
}
3、python
class Solution:
def twoSum(self, nums, target):
n = len(nums)
for i in range(n):
temp = target - nums[i]
if temp in nums:
j = nums.index(temp)
if i == j:
continue
else:
return i, j
if __name__ == '__main__':
nums = [1, 2, 2, 5]
solu = Solution()
i, j = solu.twoSum(nums, 4)
print i, j
三、哈希表法
哈希表方法的详述,请见下面这篇博文–详谈哈希表
1、c语言
解题思路
一个动态查找的过程。对于每一个 n u m s [ i ] nums[i] nums[i] ,我们要寻找剩下的数中是否存在 t e m p ( t e m p = t a r g e t − n u m s [ i ] ) temp(temp=target-nums[i]) temp(temp=target−nums[i]) ,最后返回的是下标。这里用哈希表来实现查找过程,如果不存在那么就在哈希表中对应位置插入一个新结点(结点记录了 n u m s [ i ] 和 i nums[i]和i nums[i]和i)
#include<stdio.h>
#include<malloc.h>
#include<math.h>
// 用c语言实现哈希表
struct MyNode
{
int data; // 存放数值
int index; // 用来存放下标
struct MyNode* next;
};
struct HashTbl
{
int TableSize;
struct MyNode** TheLists; // 指针的数组
};
int NextPrime(int n) // 求不小于n的素数
{
if(n % 2 == 0)
n++;
int i;
int temp;
for(; ; n+=2)
{
temp = 1;
for(i = 3; i <= sqrt(n); i+=2)
if(n % i == 0)
{
temp = 0;
break;
}
if(temp)
return n;
}
}
int Hash(int key, int TableSize) // 哈希函数(散列函数)
{
int ret = abs(key) % TableSize;
return ret;
}
struct HashTbl* InitializeTable(int TableSize)
{
struct HashTbl* H = (struct HashTbl*)malloc(sizeof(struct HashTbl));
int i;
H->TableSize = NextPrime(TableSize); // 若TableSize不是素数,则把其变为下一个素数
H->TheLists = (struct MyNode**)malloc(sizeof(struct MyNode*)*(H->TableSize));
for(i = 0; i<H->TableSize; i++) // 配置表头
{
H->TheLists[i] = (struct MyNode *)malloc(sizeof(struct MyNode));
H->TheLists[i]->next = NULL;
H->TheLists[i]->index = -1;
}
return H;
};
struct MyNode* Find(int key, struct HashTbl* H)
{
struct MyNode* P;
struct MyNode* L;
L = H->TheLists[Hash(key, H->TableSize)];
P = L->next;
while(P!=NULL && P->data != key)
{
P=P->next;
}
return P;
};
void Insert(int key, struct HashTbl* H, int Index)
{
struct MyNode* Pos;
struct MyNode* L;
Pos = Find(key, H);
if(Pos == NULL)
{
struct MyNode* NewCell = (struct MyNode*)malloc(sizeof(struct MyNode));
L = H->TheLists[Hash(key, H->TableSize)];
NewCell->next = L->next;
L->next = NewCell;
NewCell->data = key;
NewCell->index = Index;
}
}
void FreeHashTable(struct HashTbl* H, int TableSize)
{
int i = 0;
struct MyNode* temp = NULL, *deleteNode = NULL;
for(i = 0; i< TableSize; i++)
{
temp = H->TheLists[i];
while(temp)
{
deleteNode = temp;
temp = temp->next;
free(deleteNode);
}
}
free(H);
}
// 基本思路:遍历数组,对于每次的值nums[i],可以得到temp=target-nums[i],
// 然后去哈希表中查找是否存在temp,若存在则输出两个数的小标,若不存在就
// 把nums[i]插入到哈希表中。
int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{
struct HashTbl* HashforIndex = InitializeTable(numsSize);
int temp, i;
*returnSize = 0;
int *output = NULL;
for(i = 0; i< numsSize; i++)
{
temp = target - nums[i];
struct MyNode* findNode = Find(temp, HashforIndex);
if(findNode != NULL) // 找到了temp
{
output = (int *)malloc(2*sizeof(int));
*returnSize = 2;
*output = findNode->index;
*(output + 1) = i;
return output;
}
else
Insert(nums[i], HashforIndex, i);
}
FreeHashTable(HashforIndex, HashforIndex->TableSize);
return output;
}
int main()
{
int *a = NULL;
int nums[4] = {2,7,11,15};
int* returnS;
a = twoSum(nums, 4, 9, returnS);
if(*returnS == 2)
printf("%d %d", a[0], a[1]);
free(a);
return 0;
}
2、c++语言
本方法用unordered_map 底层实现的哈希表。更多的unordered_map 用法,请看c++中unordered_map的用法的详述(包含unordered_map和map的区别)
#include<iostream>
#include<unordered_map>
#include<vector>
using namespace std;
// c++: 哈希表法
// 遍历数组A{
// 对每个A[i],取得temp=target-Ai;
// 在hash表中寻找temp,一旦找到,返回;
// 如果没有找到,把temp放到hash表里
// }
class Solution{
public:
vector<int> twoSum(vector<int>& nums, int target)
{
unordered_map<int, int> mymap;
vector<int> ans;
int temp;
for(int i = 0; i < nums.size(); i++)
{
temp = target - nums[i];
if(mymap.find(temp) != mymap.end() && mymap[temp] != i)
{
ans.push_back(mymap[temp]);
ans.push_back(i);
return ans;
}
else{
mymap[nums[i]] = i;
}
}
return ans;
}
};
int main()
{
vector<int> nums{2, 7, 11, 15};
vector<int> ans;
Solution sol;
ans = sol.twoSum(nums, 9);
if(!ans.empty())
cout << ans[0] << ' ' << ans[1] << endl;
return 0;
}
3、python
这里通过字典来模拟哈希表查找过程。
class Solution:
def twoSum(self, nums, tatget):
mymap = {}
for index, num in enumerate(nums):
mymap[num] = index
for i in range(len(nums)):
temp = tatget - nums[i]
if mymap.get(temp) is not None and i != mymap.get(temp):
return i, mymap.get(temp)
if __name__ == '__main__':
nums = [1, 2, 2, 5]
solu = Solution()
i, j = solu.twoSum(nums, 4)
print(i, j)