掘金 #日新计划更文活动
题目
给定一个整数数组 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) 的算法吗?
解题思路🙋🏻 ♀️
在遍历数组时,计算每个元素与目标值的差,并检查该差值是否已在哈希表中。如果存在,返回当前元素的索引和哈希表中差值的索引。否则,将当前元素及其索引存入哈希表。关键细节是在将元素存入哈希表前先进行查找,确保不会因为数组中的重复值而返回相同的索引。
边界思考🤔
代码
错误代码
**class** Solution {
**func** twoSum(_ nums: [Int], _ target: Int) -> [Int] {
**var** dict:[Int:Int] = [:]
**for** (index, num) **in** nums.enumerated() {
dict[num] = index
**if** **let** otherIndex = dict[target - num] {
**return** [index, otherIndex]
}
}
**return** []
}
}
修改后的
class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var dict:[Int:Int] = [:]
for (index, num) in nums.enumerated() {
if let otherIndex = dict[target - num] {
return [otherIndex, index] // 注意顺序,因为字典中的数字是先出现的
}
dict[num] = index
}
return []
}
}
时空复杂度分析
O(n)
一句话解题概念
在遍历数组时,计算每个元素与目标值的差,并检查该差值是否已在哈希表中。如果存在,返回当前元素的索引和哈希表中差值的索引。否则,将当前元素及其索引存入哈希表。关键细节是在将元素存入哈希表前先进行查找,确保不会因为数组中的重复值而返回相同的索引。
使用场景与应用
1. 学习的概念:
-
哈希表 / 字典:这是本题的核心概念。哈希表允许我们实现O(1)的查找时间,这使得我们可以在不遍历整个数组的情况下查找特定的值。
-
双指针技巧:尽管在此题中不是必要的,但在许多类似的题目中,双指针(如快慢指针)都是一个常用的策略,特别是当涉及到可能的循环或查找特定的配对时。
2. 实际应用场景及技术点:
- 缓存系统:例如,一个在线购物网站可能需要快速查找商品的价格。这可以通过将商品ID作为键,商品价格作为值,存储在哈希表中来实现。
- 技术点:哈希表的O(1)查找。
- 数据库查询优化:哈希索引可以帮助数据库快速匹配特定的行或值。
- 技术点:哈希索引
- 查找重复的数据:例如,在一个文件中查找重复的行或在图像中查找重复的像素。
- 技术点:哈希表存储已经看到的值。
3. iOS app 开发的实际使用场景:
- 用户配置设置:如果一个iOS app允许用户自定义设置,这些设置可以存储在一个字典中,其中键是设置的名称,值是用户选择的值。
- 技术应用:使用Swift中的字典快速查找和更新设置。
- 缓存网络数据:为了避免频繁的网络请求和提高加载速度,app可能会缓存一些常用的数据。例如,社交媒体app可能会缓存用户的帖子或图片。
- 技术应用:使用字典将数据ID或URL映射到缓存的数据。
- 实现自动完成功能:当用户在搜索框中键入时,app可以使用哈希表来快速查找和推荐相关的搜索项。
- 技术应用:使用字典存储关键词和相关的推荐。
这题教给我们的是,知道数据结构的性能特点并能够在实际场景中恰当地使用它们,可以极大地提高代码的效率和性能。
错误与反思
这一题的关键在于使用哈希表(在 Swift 中是字典)以实现 O(1) 的查找时间。以下是一些常见的易错点:
- 更新字典的顺序:最常见的错误是先更新字典,然后再检查
target - num。这可能会导致,当解决方案包含两个相同的数字时,返回相同的索引两次。 - 返回索引的顺序:当我们找到解决方案时,我们需要确保按照正确的顺序返回索引。因为我们是在处理后面的数字时找到先前数字的,所以应该首先返回字典中的索引。
- 处理重复值:字典的键是唯一的,所以当我们遇到数组中的重复值时,它会覆盖之前的值。但是,由于我们是在更新字典之前检查
target - num,所以这并不是问题。 - 不考虑字典大小:由于我们只是查找目标的两个数字,我们不需要将所有数字存储在字典中。只需存储直到找到答案为止的数字。
- 没有返回值:在所有循环结束后,我们应该确保有一个返回语句来处理没有答案的情况。
- 忘记题目要求:题目指出答案只会有一个,并且同一个元素不会使用两次。确保代码考虑到了这些要求。