问题描述
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.
给定一个整数数组,返回两个数字的索引,使它们加起来等于一个特定的目标。
可以假设每个输入将只有一个解决方案,并且不能两次使用相同的元素。
给定 nums = [2, 7, 11, 15], target = 9,
因为nums[0] + nums[1] = 2 + 7 = 9,
因此返回 [0, 1].
python 实现
实现一:
直接利用 python 列表和切片的性质,在列表剩下的部分里查找是否存在能与当前相加得到目标值的数。虽然看上去代码量很少,但是这种方法存在的问题是,每次查找都需要进行切片操作,而 python 的切片操作每次都会使用新的内容来存储切片得到的结果,因此这种方法会比较耗内存。
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
for i, n in enumerate(nums):
if target-n in nums[i+1: ]:
return [i, nums[i+1: ].index(target-n)+i+1]
实现二:
使用散列表(比如字典)来记录已经出现过的值,以值作为 key,索引作为 val。这样做的好处是,一方面可以直接根据值来获取对应在列表里的索引,另一方面,散列表的读取速度比较快,时间和空间上消耗比较小。
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
dic = {} # key: value, val: index
for i, n in enumerate(nums):
if target-n in dic.keys():
return [dic[target-n], i]
else:
dic[n] = i
特殊情况
如果入参 nums 是一个满足升序的有序表,由于肯定存在有且只有一组数相加之和等于目标值,因此其他组合的结果要么大于目标值,要么小于目标值。那我们就可以分别在首尾用一个变量记录索引,两个索引逐步往中间靠拢,必然能找出符合要求的两个索引值。
这种实现方法能避免创建额外的内存空间,而且时间复杂度也相对较小,但是前提条件有点太理想。如果入参不是有序的,再手动排序使用这个方法,找到两个值之后还要回到原数组去找到相应的索引,这样的操作也太复杂了。不过这也是一种思路的拓展啦,毕竟从首尾分别使用一个指针进行定位这种技巧在很多算法题都是有用的。
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
head = 0
tail = len(nums) - 1
while head < tail:
if nums[head] + nums[tail] == target:
return [head, tail]
elif nums[head] + nums[tail] > target:
tail -= 1
else:
# nums[head] + nums[tail] < target
head += 1
return [None, None]
链接:https://leetcode.com/problems/two-sum/