查找实战
案例一:两数之和
题目描述: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
解题思路: 首先想到暴力解决,即第一遍遍历数组,第二遍遍历当前遍历值之后的元素,但是时间复杂度为O(n^2)
。
于是想着优化,用二分查找法,先将输入数组进行排序(从小到大),但是这样元素的索引也会发生变化,于是在排序前先使用一个额外的数组拷贝一份原来的数组,对于两个相同元素的索引问题,使用一个bool型变量辅助将两个索引都找到,总的时间复杂度为O(n)+O(nlogn) = O(nlogn)
代码如下:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
record = dict()
nums_copy = nums.copy()
sameFlag = True;
nums.sort()
l,r = 0,len(nums)-1
while l < r:
if nums[l] + nums[r] == target:
break
elif nums[l] + nums[r] < target:
l += 1
else:
r -= 1
res = []
for i in range(len(nums)):
if nums_copy[i] == nums[l] and sameFlag:
res.append(i)
sameFlag = False
elif nums_copy[i] == nums[r]:
res.append(i)
return res
但是还有另外一种更方便的解法,通过list(enumerate(nums))
开始实现下标和值的绑定,不用专门的再copy加bool判断。
代码如下:
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
# res = dict()
# for index in range(len(nums)):
# res[nums[index]] = index
# for i,num in enumerate(nums):
# j = res.get(target-num)
# if j is not None and j!=i:
# return [i,j]
nums = list(enumerate(nums))
nums.sort(key =lambda x:x[1])
print(nums)
l = 0
r = len(nums)-1