
本文详解利用双指针技术在两个已排序数组中线性时间查找公共元素的正确实现,对比二分搜索等替代方案的时间复杂度,并提供可直接运行的代码示例与关键注意事项。
本文详解利用双指针技术在两个已排序数组中线性时间查找公共元素的正确实现,对比二分搜索等替代方案的时间复杂度,并提供可直接运行的代码示例与关键注意事项。
在处理已排序数组的交集问题(即查找“重复元素”——更准确地说,是两数组的公共元素)时,双指针遍历是最经典、最优的解决方案。你提供的 findDuplicatesFinalVersion 方法完全符合这一范式,逻辑严谨、实现简洁,且时间复杂度达到理论下界 O(m + n),其中 m 和 n 分别为两数组长度。
该算法的核心思想是:
- 利用数组已排序的特性,避免暴力嵌套循环(O(m×n))或额外空间哈希(不必要且破坏有序优势);
- 维护两个指针
index1和index2,分别指向arr1和arr2的当前待比较位置; - 比较
arr1[index1]与arr2[index2]:- 若前者更小 →
index1++(跳过不可能匹配的较小值); - 若相等 → 计数加一,并同步推进两个指针(因题目明确说明“各数组内部无重复”,故无需跳过连续相同元素);
- 若后者更小 →
index2++。
- 若前者更小 →
✅ 正确性验证示例:
int[] arr1 = {1, 3, 5, 7, 9};
int[] arr2 = {3, 4, 5, 8, 9, 10};
System.out.println(findDuplicatesFinalVersion(arr1, arr2)); // 输出: 3 (对应 3,5,9)
⚠️ 注意事项:
-
前提强依赖:此算法严格要求两数组升序排列且各自无重复元素(如题干所述)。若存在内部重复,需额外去重逻辑(如跳过
arr1[index1] == arr1[index1-1]); -
边界安全:
while条件index1 精确控制越界,无需额外检查; - 空间最优:仅使用 O(1) 额外空间,优于哈希表方案的 O(min(m,n));
? 对比其他策略:
-
二分搜索法:遍历较短数组,对每个元素在较长数组中二分查找。时间复杂度为 O(min(m,n) × log(max(m,n)))。当数组长度差异极大(如
n=10, m=10^6)时可能略优,但常数因子高,且丧失缓存局部性; - 暴力法/未排序处理:需先排序(O(m log m + n log n))再双指针,或哈希集合(O(m+n) 时间但非原地),均不适用于本题“输入已排序”的优化场景。
? 总结:你的实现不仅是“正确”的,更是该问题的标准最优解。在课程 benchmark 中,它应显著快于未排序版本(含预排序开销)和二分搜索版本(尤其当两数组长度接近时)。如需扩展功能(如返回具体公共元素列表而非仅计数),只需将 count++ 替换为 list.add(arr1[index1]) 即可,复杂度不变。










