小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
一、题目
Given an array of integers, return indices of the two numbers such that they add up to a specific target.You may assume that each input would have exactly one solution, and you may not use the same element twice.
翻译:给定一个全是int的数组和一个整数target,要求返回两个下标,使得数组当中这两个下标对应的和等于target。你可以假设一定值存在一个答案,并且一个元素不能使用两次。
二、解答
找两个数和等于target,第一反应就是暴力枚举。假设数组长度是n,那么一个 的循环就可以搞定。用Python的话,分分钟就可以写出代码。
for i in range(len(array)):
for j in range(len(array)):
if array[i] + array[j] == target:
return [i, j]
这样做当然是正确的,但显然不是最好的答案。 根据经验,一般情况下O(n²)的算法都不是最优解。
其实最优解是使用map,在这道题当中,我们可以将元素和它在数组当中对应的下标存储进map当中。也就是说我们把所有数据对应的下标,存储好了之后,我们在遍历的时候,就可以去掉j那一重循环,而直接判断target-a[j] 在不在map当中即可。
伪代码如下:
for i in range(len(array)):
map[array[i]] = i;
if target - array[i] in map:
return [i, map[target - array[i]]]
这个算法看起来没什么问题,但是如果你这么写出代码来提交一定过不了。因为有一种隐藏的情况没有考虑到,题目当中说了,同一个元素不能使用两次,但是并没有说数组当中没有重复的元素。map的使用有一个限制,就是不能有key值相同的元素。如果数组当中存在重复的元素,那么后面读到的数据会覆盖前面的。覆盖会产生什么问题呢?会导致我们没有办法判断元素出现的次数。
解决办法是,通过利用加法交换律以及元素出现的先后顺序,再结合map,我们只需要一次遍历就可以找到答案。就算出现重复元素,也没有关系,因为我们是先判断存不存在,再更新map。
伪代码如下:
for i in array.length:
if target - array[i] in map:
return i, map[target - array[i]]
else:
map.put(array[i], i)