在算法面试中,数组相关的题目占据了相当大的比重,它们不仅考察了候选人对数据结构的理解,还检验了解决问题的逻辑思维能力和编程技巧。其中,“三数之和”是一道经典的题目,它要求在给定的一个整数数组中找到所有独特的三元组,使得这三个数之和为零。这个问题看似简单,实则蕴含了多种优化思路,是评估算法设计能力的好题。
给定一个包含 n 个整数的数组 nums
,判断 nums
中是否存在三个元素 a、b、c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:
要解决这个问题,最直接的方法是三层嵌套循环遍历数组,检查所有可能的三元组是否满足条件。然而,这种方法的时间复杂度为 O(n^3),在数组较大时效率极低,难以通过面试。因此,我们需要寻找更高效的算法。
一个优化的思路是,首先对数组进行排序,然后利用排序后的数组特性来减少不必要的遍历。排序后,我们可以通过固定一个元素,然后使用双指针技术来寻找另外两个元素,从而将问题转化为一个两数之和的问题,其时间复杂度可以降低到 O(n^2)。
步骤一:排序
首先对数组进行排序,排序的时间复杂度为 O(n log n)。
步骤二:固定一个元素,双指针查找
nums
,将当前元素记为 nums[i]
,作为三元组中的第一个数。left
和 right
,分别指向 i+1
和数组末尾 n-1
。nums[i] + nums[left] + nums[right]
的值:left
和 right
指针(注意跳过重复元素,以避免重复的三元组)。left
指针右移。right
指针左移。left
大于等于 right
时,退出内层循环,继续遍历数组中的下一个元素。以下是该算法的 Python 实现:
def threeSum(nums):
nums.sort() # 先对数组进行排序
result = []
for i in range(len(nums) - 2):
# 跳过重复的元素,避免重复的三元组
if i > 0 and nums[i] == nums[i - 1]:
continue
left, right = i + 1, 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:
left += 1
else:
right -= 1
return result
# 示例
nums = [-1, 0, 1, 2, -1, -4]
print(threeSum(nums))
# 输出: [[-1, -1, 2], [-1, 0, 1]]
通过“三数之和”这道面试题,我们不仅可以锻炼数组和排序相关的知识,还能深入理解双指针技术的应用,以及如何通过优化算法来减少不必要的计算,提升程序的执行效率。希望本章内容能帮助你在算法面试中更加游刃有余。