千里之行,始于足下,从第一题开启算法通关之旅。
两数之和
原题地址:两数之和
题目描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例3:
输入:nums = [3,3], target = 6
输出:[0,1]
思路:
首先是最容易想到的暴力解法,使用两层循环找出所有的两两组合。暴力解法的时间复杂度是 O ( n 2 ) O(n^2) O(n2),因为内外循环两次,空间复杂度为 O ( 1 ) O(1) O(1),因为每次存储的仅是两个遍历到的数组元素。
改进版的话,会考虑到使用排序+双指针。即排序后,使用首尾双指针来遍历数组中的元素,两数相加若大于目标值,则尾指针向前移动;若小于目标值,则首指针向后移动;若等于目标值,则记录。改进算法的时间复杂度上界为 O ( n l o g n ) O(nlogn) O(nlogn),主要在于排序的方法,空间复杂度不确定,取决于排序算法自身的实现过程。
最为有效的解决方法是用空间换时间,即考虑使用哈希表。
在python当中,基于哈希表的数据结构是字典(dict),因此,我们考虑使用字典来记录遍历过的数字,当前遍历到的数字和字典里存储过的数字相加等于目标值时,即返回。字典的结构可以设置如下:
d[array[index]] = index
代码如下:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
d = {}
for i in range(len(nums)):
if target - nums[i] in d:
return [d[target - nums[i]], i]
else:
d[nums[i]] = i
总结
这道题目,其实我在2021年的美团实习生面试的时候遇到过,不由得感叹当初只刷过个位数的题的自己居然有勇气面试大厂的算法岗,我还记得在面试过程中,表现的手忙脚乱,当时写了个暴力解法,还写错了,搞得我也尴尬,面试官也尴尬。因为当时面试官的要求是找到数组中所有和等于目标值的两数,难度还是要比这道题高一点的。虽然最后凉了,但也是给了我宝贵的经验和冲击,意识到自己还有很大的不足,才有了之后的下定决心,奋起直追。
从今天起,算法王,我当定了!