「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」。
前言
一直都计划学习数据结构与基本算法,但是平时都看一阵停一阵。今天借着掘金的更文活动,我准备从LeetCode的HOT100开始,每天完成1~2道习题,希望通过这种方式养成持续学习的习惯。因为我是做iOS开发的,主要是用Objective-C语言,最近也在学习Swift,所以本系列的题解都将使用swift语言完成,本文更新的是LeetCode中HOT100的第1题001两数之和。
题目
给定一个整数数组 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]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
分析
本题的题目意思很清晰,从整数数组nums中找出和为指定值target的两个数,并返回这两个数的下标,题目也明确指出只会存在一个答案。针对这个问题,基本思路分为三种:
第一种解法是暴力解法,枚举数组中的每一个数 x,寻找数组中是否存在 target - x。该解法的的缺点是复杂度比较高,为O(n^2)。
第二种解法是先排序,然后使用头尾双指针法进行判断,该方法的优点是复杂度可以降到O(n*lgn),但是缺点是排序过程中要记录对应的下标就比较麻烦。
第三种解法是以空间换时间,用一个字典(key为整数数值x,value为x对应的下标)来记录当前已经查询过的整数和其对应的下标,记录规则是对于每一个 x,我们首先查询字典中是否存在 target - x,如果存在,则直接将当前x和字典中对应的值返回即可,如果不存在,则将 x 插入到字典表中,即可保证不会让 x 和自己匹配。该方法的优点是时间复杂度很低,为O(n),缺点是需要一个字典来保存数据。
显然,上述三种方法中,第三种方法是最优解,所以我们也选择这种方法完成题解。
题解
class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var tempDic: Dictionary<Int, Int> = [Int : Int]()
for i in 0..<(nums.count) {
let num1: Int = nums[i] //当前值x
let num2:Int = target - num1 //目标值target - x
if tempDic.index(forKey: num2) != nil {
//存在则直接返回结果
return [i, tempDic[num2] ?? 0]
} else {
//不存在则将x及其对应的下标保存到字典中
tempDic[num1] = i
}
}
return []
}
}