返回
用双指针法亲手捏出三数之和的解法,从容拿捏!
后端
2024-01-02 17:21:42
在浩瀚的算法世界里,三数之和(3Sum)问题如同璀璨的明珠,熠熠生辉。它不仅考验程序员的算法思维,更启迪着他们在面对复杂问题时以巧妙的方式寻找解决方案。本次,我们将携手踏上征服三数之和问题的征途,手把手引导您掌握双指针法的精髓,让您轻松破解这道经典算法难题。
问题背景
假设您面前有一张扑克牌,而这张牌里包含了无数张数字牌。现在,需要您从这些数字牌中挑出三张牌,使得它们的和为0。比如说,如果牌面数字为[-1, 0, 1, 2, -2, 1],那么其中就有两组数字满足要求,分别是[-1, 0, 1]和[-2, 1, 1]。
那么,怎样才能高效地找到所有满足要求的三元组呢?这就是三数之和问题(3Sum)的精髓所在。
双指针法的威力
双指针法是一种巧妙的算法策略,常用于处理有序数组或链表中的元素。在解决三数之和问题时,双指针法更是发挥了举足轻重的作用。
具体来说,双指针法的操作步骤如下:
- 首先,将数组中的元素按照升序排列。
- 然后,分别设置两个指针,一个指向数组的第一个元素,另一个指向数组的最后一个元素。
- 然后,依次计算两个指针指向的元素之和。
- 如果元素之和等于目标和(本题中为0),则找到一组满足要求的三元组。
- 如果元素之和大目标和,则将右侧指针左移一位。
- 如果元素之和小于目标和,则将左侧指针右移一位。
- 重复以上步骤,直到遍历完整个数组或找到所有满足要求的三元组。
代码实现
def three_sum(nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
# 对数组进行升序排序
nums.sort()
# 初始化结果数组
result = []
# 遍历数组
for i in range(len(nums)):
# 跳过重复的元素
if i > 0 and nums[i] == nums[i - 1]:
continue
# 设置左右指针
left = i + 1
right = len(nums) - 1
# 计算和
while left < right:
total = nums[i] + nums[left] + nums[right]
# 如果和等于目标和,则找到一组满足要求的三元组
if total == 0:
result.append([nums[i], nums[left], nums[right]])
# 跳过重复的元素
while left < right and nums[left] == nums[left + 1]:
left += 1
while left < right and nums[right] == nums[right - 1]:
right -= 1
# 移动指针
left += 1
right -= 1
# 如果和大目标和,则将右侧指针左移一位
elif total > 0:
right -= 1
# 如果和小于目标和,则将左侧指针右移一位
else:
left += 1
# 返回结果数组
return result
复杂度分析
- 时间复杂度:O(n^2)。因为需要遍历数组中的每个元素,并且对于每个元素,都需要遍历剩下的所有元素,因此时间复杂度为O(n^2)。
- 空间复杂度:O(1)。因为不需要额外的空间来存储数据,因此空间复杂度为O(1)。
结语
三数之和问题是算法面试中的常见问题,也是算法竞赛中的经典题目。通过双指针法的巧妙运用,我们可以高效地找到所有满足要求的三元组,并快速检查这些数字是否满足目标和。希望这篇博文能帮助您深入理解三数之和问题,并掌握双指针法的精髓。如果您对算法问题有任何疑问,欢迎随时与我联系。