Swift 数据结构与算法(六) 数组 + Leetcode 剑指 Offer 57. 和为s的两个数字

70 阅读2分钟

概念

题目

剑指 Offer 57. 和为s的两个数字

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

 

示例 1:

输入: nums = [2,7,11,15], target = 9
输出: [2,7] 或者 [7,2]

示例 2:

输入: nums = [10,26,30,31,47,60], target = 40
输出: [10,30] 或者 [30,10]

 

限制:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^6

解题思路🙋🏻‍ ♀️

假设输入数组是 [2,7,11,15],目标数是 9。

初始状态,left 指向第一个元素,right 指向最后一个元素:

nums:  2 -> 7 -> 11 -> 15
       ^                 ^
       leftPointer      rightPointer

第一次迭代,leftPointerrightPointer 指向的元素之和是 17,大于目标数 9,所以我们将 rightPointer 向左移动一位:

nums:  2 -> 7 -> 11 -> 15
       ^           ^
       leftPointer  rightPointer

第二次迭代,leftPointerrightPointer 指向的元素之和是 13,仍然大于目标数 9,所以我们再次将 rightPointer 向左移动一位:

nums:  2 -> 7 -> 11 -> 15
       ^     ^
       leftPointer  rightPointer

第三次迭代,leftPointerrightPointer 指向的元素之和是 9,正好等于目标数,所以我们找到了解答:

nums:  2 -> 7 -> 11 -> 15
       ^     ^
       leftPointer  rightPointer

所以,最终的结果就是 [2,7]。

边界思考🤔

特殊处理的情况主要是当数组中存在多对和为目标数的元素时,我们只需要返回其中任意一对即可。

以下是对应的图示:

  1. 当数组为空时,我们无法找到解答:

    nums: 
    
  2. 当数组只包含一个元素时,我们同样无法找到解答:

    nums: 1
    
  3. 当数组中所有元素的和都小于目标数时,我们无法找到解答:

    nums: 1 -> 2 -> 3 -> 4 -> 5
    target: 15
    
  4. 当数组中存在多对和为目标数的元素时,我们只需要返回其中任意一对即可:

    初始状态:
    nums: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
    target: 8
    

    结果可以是 [1, 7],也可以是 [2, 6],或者 [3, 5]。

代码

class Solution {

    func twoSum(_ nums: [Int], _ target: Int) -> [Int] {

        // 如果数组的元素个数小于等于1,那么直接返回空数组,因为没有可能的答案
        if nums.count <= 1 {
           return []
        }

        // 初始化两个指针,left 指向数组的开始,right 指向数组的结尾
        var left = 0
        var right = nums.count - 1
        // 当 left 指针小于 right 指针时,执行循环
        while left < right {
            // 如果两个指针指向的元素的和大于目标值,那么将 right 指针向左移动一位
            if nums[right] + nums [left] > target {
                right -= 1
            // 如果两个指针指向的元素的和小于目标值,那么将 left 指针向右移动一位
            } else if nums[right] + nums[left] < target {
               left += 1
            // 如果两个指针指向的元素的和等于目标值,那么返回这两个元素
            } else {
              return [nums[right], nums[left]]
            }
        }
        // 如果循环结束都没有找到答案,那么返回空数组
        return []
    }
}

时空复杂度分析

时间复杂度 O (n), 通过两个指针来寻找数组中的两个数,使得这两个数的和等于目标值。因为我们只是在原数组上进行操作,没有使用额外的数组或者字符串,所以空间复杂度是 O(1)。

截屏2023-08-02 15.08.19.png