给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
写的时候输出列表元素了,人家要求输出下标,不过这不影响。
我的思路是由于结果唯一,找到就打印结果并结束整个for循环,后面的循环没必要执行了;没找到就打印个提示。
初版代码:
nums = [2, 7, 11, 15]
def func(target):
sign=0 # 是否找到结果的标志位,0未找到,1找到
length=len(nums)
for i in range(length-1): # i从0到2
for j in range(i+1,length): # j从i+1到最后一个元素
if nums[i]+nums[j]==target:
print([nums[i],nums[j]])
sign=1
break
if sign==1: # sign为1时,不再继续外层循环,如果不加这个条件,func(22)执行到7+15时,打印完还会接着执行外层循环
break
elif (i==length-2) and (nums[i]+nums[j] != target): # 判断最后一次比较
print('target not found!')
break
这里用的都是break,是跳出当前循环,所以if的缩进与内层for一致。第二个if这里一开始想写for-else,else对应上面的for,不管哪一个for,没写出来。
写好后明显效率不高,而且第一个break可以用return,于是有了第二版:
nums = [2, 7, 11, 15]
def func(target):
sign=0
length=len(nums)
for i in range(length-1): #i从0到2
for j in range(i+1,length): # j从i+1到最后一个元素
if nums[i]+nums[j]==target:
print([nums[i],nums[j]])
sign=1
return # 相比break,找到后return就结束整个循环了,不会出现第一版注释中找到后接着执行外层循环的情况
if sign==0: # 整个循环执行完了,没找到时sign还是0
print('target not found!')
第二版的改进有2点:
- return后面的注释说了
- 没找到时的判断,第一版的太复杂。首先,因为if-elif的缩进对应内层循环,所以每次内层循环执行完,都会判断是否找到;其次,没找到时的最后一次比较太复杂,即elif。而第二版循环结束时标志位没变,那就是没找到,只需要判断标志位就行。
第三版,这是我在思考如何改进第一版时朋友写的(我写好第二版后才看的他的):
nums = [2, 7, 11, 15]
def func(target):
length=len(nums)
for i in range(length-1): # i从0到2
for j in range(i+1,length): # j从i+1到最后一个元素
if nums[i]+nums[j]==target:
return [i,j] # 由于结果唯一,找到后直接return结束整个循环
return '查无此果!'
while True:
print(func(int(input('请输入要查找的值:'))))
第三版的改进:取消了标志位,更高效。找到时直接打印,然后循环直接结束;没找到时说明外层循环执行完了,打印提示。这才符合我最初的思路。
补充:for循环即便写成
for i in range(length):
for j in range(i+1,length):
当 i=2 时,j=3;下轮循环 i 变成3,此时 j 依然为3。不会出现因下标越界导致数据出错的问题,我记得C++,有的编译器有这个问题,有的没有,那时候试了VC6.0,VS2015(也可能2017),DevCpp with MinGW,CodeBlocks with MinGW。后两个当时只是尝鲜。