问题:
给定一个整数数组 nums 和一个目标值 target ,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
我的思路:
1. 嵌套循环:外层遍历整个数组;外层判断是否有 x+y=target 的元素(或存在 target-x 的元素)。
2. 解决值和索引对应的有效手段:哈希表。
解答:
1. C语言实现
#include<stdio.h>
#include<stdlib.h> //system("pause")的头文件
int *twoSum(int *nums, int numSize, int target)
{
int i=0, j=0;
int *pBuf=(int*)malloc(2*sizeof(int)); //因为函数返回值必须是指针类型,所以这里定义的是指针类型的数组!
for(i=0;i<numSize-1;i++)
{
for(j=i+1;j<numSize;j++) //减少不必要的计算,j从i+1开始
{
if(target==nums[i]+nums[j])
{
pBuf[0]=i;
pBuf[1]=j;
return pBuf;
}
}
}
free(pBuf);
return NULL; //如果没有检索到满足条件的,那么返回NULL
}
int main(void) //表示main函数没有参数,返回值为整型
{
int nums[4]={2,7,11,15};
int *pIndex=NULL;
int target=9, numSize=4;
pIndex=twoSum(nums, numSize, target);
if(pIndex==NULL)
{
printf("Error!\n");
}
else
{
printf("The index is %d and %d!\n",pIndex[0],pIndex[1]);
free(pIndex);
}
system("pause");
return 0;
}
2. Python3实现
# 方法一:暴力法(两层遍历)。
# 第一次遍历查一个数,第二次遍历查是否存在一个数等于target-第一个数。
# 算法复杂度O(n^2)。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
length = len(nums)
for i in range(length-1):
for j in range(i+1, length): # 第二个数索引从 i+1 开始
if nums[j] == target - nums[i]:
return [i, j]
return None
# 方法二:哈希表。
# 保证元素及其索引相互对应最有效的方式是:哈希表。
# 算法复杂度:O(n)。
# 测试用例:nums = [3, 3, 1, 4],target = 5。虽然前两位元素重复了,但好在3并不满足条件,因此 hashmap[3]=0 再更新为 hashmap[3]=1 并不影响结果。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashmap = {}
for index, num in enumerate(nums):
if (target - num) in hashmap:
return [index, hashmap[target-num]]
hashmap[num] = index # 只将不能满足条件的键值对存入。
return None
######### 下面是两种错误示范 ##########
# 第一种:无法找到值对应的键。解决方法:把元素本身作为key,索引作为value。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hash = dict() # 构建哈希表的两种方式:dict() 或 {}
length = len(nums)
for i in range(length): # 将元素都存入哈希表,键是相应的索引值
hash[i] = nums[i]
for i in range(length):
if (target - hash[i]) in hash.values():
j = hash.get(target - hash[i]) # 错误!.get()函数,是获得键k对应的值values。Python3中没有通过值索引键的方式,所以要转换思想,把元素值作为键,索引值作为values
return [i, j]
return None
# 第二种:出现了冲突。解决方法:不建立完整的哈希表,如果 target-num 存在于 nums 中,则直接输出索引,而不将键值对存入哈希表。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hash = dict()
length = len(nums)
for i in range(length):
hash[nums[i]] = i # 使用元素值作为键,出现了冲突。例如nums=[3,3],target=6,输出了None。也不可!
for item in nums:
if target-item in hash.keys() and hash[target-item] != hash[item]:
return [hash[target-item], hash[item]]
return None
知识点:
1. enumrate() 函数:为可迭代对象添加序号,默认从 0 开始。一般用在 for 循环中。
enumerate(iterable [,start]),其中 iterable 是可迭代对象(字符串、列表、元组、字典),start 是序号起始值。
返回值:返回枚举对象。
nums = [1, 2, 3, 4, 5]
for index, num in enumerate(nums):
print('{}, {}'. format(index, num))
2. Python3 中 “&”、“|” 和 “and”、“or”的区别
“&”、“|” 是位运算(用于数值)
“and”、“or” 是逻辑运算(用于逻辑关系式)
Python 中的逻辑操作符有:and、or、not