题目来源
题目分析
给定一个已经按升序排序的整数数组,在其中找到两个数,使他们加起来为目标数值,最后返回这两个数的索引。返回的第一个索引需要小于第二个索引,并且索引是从1开始计算的。注意每个情况只有一组解,并且不能使用相同的元素两次。
这个题目的第一种思路是遍历,因为已经排好序了,则前后两值相加,与目标值比大小,进行相应的调整。这里始终应该注意首部的“指针”不能超过尾部的“指针”,因此遍历过程需要用while而不是for循环。
此时实现的代码为:
class Solution:
def twoSum(self, numbers, target):
"""
:type numbers: List[int]
:type target: int
:rtype: List[int]
"""
i=0
j=len(numbers)-1
while(i<j):
if(numbers[i]+numbers[j]<target):
i+=1
elif(numbers[i]+numbers[j]>target):
j-=1
else:
return [i+1,j+1]
第二种思路使用了字典,利用了字典其中的enumerate()内置函数,这个函数在先前也有所涉及,对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值,enumerate多用于在for循环中得到计数。因为这里我们是需要先比较值,然后得到它的索引,所以可以考虑这种思路。其代码如下:
class Solution:
def twoSum(self, numbers, target):
"""
:type numbers: List[int]
:type target: int
:rtype: List[int]
"""
dic={}
for i,number in enumerate(numbers):
if((target-number) in dic):
return [dic[target-number]+1,i+1]
dic[number]=i
需要注意的是将列表中的元素放入字典时,是将值作为下标,将下标作为值,这样做时有一定意义的。如果反向了,即使你得到了相对应的值,你也无法知道它的下标是多少,所以这里一定要注意。
还有一种思路是二分法查找,它主要应用于已经排序好的数组之中。其大致的思想为:首先将给定值key与字典中间位置上元素的关键码(key)比较,如果相等,则检索成功;否则,若key小,则在字典前半部分中继续进行二分法检索;若key大,则在字典后半部分中继续进行二分法检索。这样,经过一次比较就缩小一半的检索区间,如此进行下去,直到检索成功或检索失败。偶数个取中间2个其中任何一个作为中间元素。二分法检索是一种效率较高的检索方法,要求字典在顺序表中按关键码排序。但是这里是要我们将两者的和与target比较而不是单一的元素,所以有些复杂。别人的代码如下:
def twoSum(self, numbers, target):
for i in xrange(len(numbers)):
l, r = i+1, len(numbers)-1
tmp = target - numbers[i]
while l <= r:
mid = l + (r-l)//2
if numbers[mid] == tmp:
return [i+1, mid+1]
elif numbers[mid] < tmp:
l = mid+1
else:
r = mid-1
注意这里它不是和target比较,而是将其化成和其中某个元素进行比较。