这个问题是一个经典的两个有序数组的交集问题,结合了双指针法来高效地求解交集并确保交集结果是按从大到小的顺序排列。
实现思路总结
-
双指针法:
- 我们使用两个指针分别从两个数组的末尾开始遍历,因为数组是升序排列的,逆向处理可以直接构建从大到小的交集。
- 每次比较两个指针所指向的元素:
- 如果相等,将该元素添加到结果中,并移动两个指针。
- 如果
a[i] > b[j],说明a[i]不可能在交集中,因此移动a的指针。 - 如果
b[j] > a[i],则移动b的指针。
-
结果的顺序:
- 由于我们是从数组的末尾开始处理,所以交集结果自然是从大到小排列。
代码实现
def solution(a, b):
# 双指针初始化在数组末尾
i, j = len(a) - 1, len(b) - 1
result = []
# 双指针法计算交集
while i >= 0 and j >= 0:
if a[i] == b[j]:
# 如果两个指针指向的元素相等
result.append(a[i])
i -= 1
j -= 1
elif a[i] > b[j]:
# 如果a指针的值大于b指针的值,移动a指针
i -= 1
else:
# 如果b指针的值大于a指针的值,移动b指针
j -= 1
return result
# 测试用例
if __name__ == '__main__':
print(solution([1, 2, 3, 7], [2, 5, 7]) == [7, 2]) # 输出应为 True
print(solution([1, 4, 8, 10], [2, 4, 8, 10]) == [10, 8, 4]) # 输出应为 True
print(solution([3, 5, 9], [1, 4, 6]) == []) # 输出应为 True
print(solution([1, 2, 3], [1, 2, 3]) == [3, 2, 1]) # 输出应为 True
代码说明
-
初始化:
i和j分别初始化为两个数组的最后一个元素索引。result是用来存储交集结果的数组。
-
双指针循环:
- 循环条件是
i >= 0且j >= 0,即两个指针都未越界。 - 每次比较
a[i]和b[j]:- 如果相等,说明找到了交集元素,加入
result,并将两个指针都向左移动。 - 如果
a[i] > b[j],说明a[i]不可能在交集中,移动i。 - 如果
b[j] > a[i],说明b[j]不可能在交集中,移动j。
- 如果相等,说明找到了交集元素,加入
- 循环条件是
-
最终返回:
- 最后返回
result,即交集元素按从大到小的顺序排列。
- 最后返回
测试结果
- 对于输入
[1, 2, 3, 7]和[2, 5, 7],交集是[7, 2]。 - 对于输入
[1, 4, 8, 10]和[2, 4, 8, 10],交集是[10, 8, 4]。 - 对于输入
[3, 5, 9]和[1, 4, 6],没有交集,返回[]。 - 对于输入
[1, 2, 3]和[1, 2, 3],交集是[3, 2, 1]。
复杂度分析
-
时间复杂度:
- 每次比较和移动指针的操作是常数时间操作,指针遍历整个数组的长度。由于每个数组的长度分别为
n和m,所以总时间复杂度为O(n + m),其中n和m分别是数组a和b的长度。
- 每次比较和移动指针的操作是常数时间操作,指针遍历整个数组的长度。由于每个数组的长度分别为
-
空间复杂度:
- 我们只使用了常数额外空间来存储指针和结果数组,因此空间复杂度为
O(k),其中k是交集的大小。
- 我们只使用了常数额外空间来存储指针和结果数组,因此空间复杂度为
总结
通过双指针法,我们能够高效地计算两个有序数组的交集,并且在遍历的过程中直接得到从大到小的排序。这种方法的时间复杂度为 O(n + m),非常适合用于处理有序数组的交集问题。