Swift 数据结构与算法( 32) + Leetcode1. 两数之和(哈希表)

101 阅读4分钟

掘金 #日新计划更文活动

题目

1. 两数之和

给定一个整数数组 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) 的查找时间。以下是一些常见的易错点:

  1. 更新字典的顺序:最常见的错误是先更新字典,然后再检查 target - num。这可能会导致,当解决方案包含两个相同的数字时,返回相同的索引两次。
  2. 返回索引的顺序:当我们找到解决方案时,我们需要确保按照正确的顺序返回索引。因为我们是在处理后面的数字时找到先前数字的,所以应该首先返回字典中的索引。
  3. 处理重复值:字典的键是唯一的,所以当我们遇到数组中的重复值时,它会覆盖之前的值。但是,由于我们是在更新字典之前检查 target - num,所以这并不是问题。
  4. 不考虑字典大小:由于我们只是查找目标的两个数字,我们不需要将所有数字存储在字典中。只需存储直到找到答案为止的数字。
  5. 没有返回值:在所有循环结束后,我们应该确保有一个返回语句来处理没有答案的情况。
  6. 忘记题目要求:题目指出答案只会有一个,并且同一个元素不会使用两次。确保代码考虑到了这些要求。