返回
巧用指针,从有序数组中找出两数和,难题秒变易如反掌!
前端
2023-12-02 04:23:04
最近,我碰到了一个有趣的问题:从一个已排序的数组中找出两个数,使得它们的和正好是输入的那个数字。而且,要将所有的组合列出来。
拿到这个问题,我第一时间想到的方法是用双重 for
循环遍历数组,穷举出所有的组合,再检查每个组合的和是否等于输入的数字。
def two_sum_brute_force(nums, target):
"""
暴力法求解两数之和问题。
:param nums: 有序数组
:type nums: list
:param target: 目标和
:type target: int
:return: 满足条件的两个数的组合,形式为[(num1, num2), ...]
:rtype: list
"""
result = []
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target:
result.append((nums[i], nums[j]))
return result
这个方法虽然简单,但时间复杂度是 O(n^2)
,对于大规模数组来说,效率非常低。
有没有更高效的方法来解决这个问题呢?
有的,那就是双指针法!
双指针法是一种用来解决有序数组中查找问题的经典算法。它的基本思想是:使用两个指针,一个指针指向数组的开头,另一个指针指向数组的结尾。然后,比较这两个指针指向的元素的和与目标和。如果和大于目标和,则将右指针向左移动;如果和小于目标和,则将左指针向右移动。重复这个过程,直到找到和等于目标和的两个元素。
def two_sum_two_pointers(nums, target):
"""
双指针法求解两数之和问题。
:param nums: 有序数组
:type nums: list
:param target: 目标和
:type target: int
:return: 满足条件的两个数的组合,形式为[(num1, num2), ...]
:rtype: list
"""
result = []
left = 0
right = len(nums) - 1
while left < right:
sum = nums[left] + nums[right]
if sum == target:
result.append((nums[left], nums[right]))
# 跳过重复的元素
left += 1
while left < right and nums[left] == nums[left - 1]:
left += 1
# 跳过重复的元素
right -= 1
while left < right and nums[right] == nums[right + 1]:
right -= 1
elif sum < target:
left += 1
else:
right -= 1
return result
双指针法的速度要快得多,时间复杂度是 O(n)
。
除了双指针法,还有其他方法可以解决两数之和问题,比如哈希表法。但是,双指针法是最简单、最容易理解的方法之一。
掌握了双指针法,你就能轻松解决很多数组查找问题。