解题思路
找出交集元素。我们可以先将两个数组排序。排序之后,我们就可以知道这个每个数组的最大值和最小值。此时,有一种极端情况需要考虑,就是第一个数组的最大值小于第二个数组的最小值或者第一个数组的最小值大于第二个数组的最大值,此时这两个数组是不存在交集的。否则,我们就需要去遍历这两个数组,然后定义两个指针,分别代表两个数组的下标,从0开始,直到其中的一个数组遍历完成,我们就确定了重复的元素,最后返回这个数组。
- 排序。
Arrays.sort(nums1);
Arrays.sort(nums2);
- 判断是否存在极端情况。
if (nums1[nums1.length - 1] < nums2[0] || nums2[nums2.length - 1] < nums1[0]) {
return null;
}
- 遍历数组。
首先,遍历之前我们可以先想想这样一个问题。如果nums1(排序后)中的元素是[1, 2, 2, 2, 2, 3],这种情况,我们是不是只需要判断一次2就 行,知道我们找到下一个不是2的元素再开始和num2比较。
for () { // 控制外层循环
if (nums1[i] < nums2[j]) {
// i需要加1,继续和num2[j]比较,
int current = nums1[i];
while (++i < len1) { // 优化
if (nums1[i] > current) { // 直到nums1[i] 和 current 不相等时,跳出循环。
// 此处大于,是因为之前排过序了,nums1[i] <= nums1[i + 1]
break;
}
}
}
}
- 返回。将List转为int[]。
int[] res = new int[nums.size()];
for (int idx = 0; idx < nums.size(); idx++) {
res[idx] = nums.get(idx);
}
代码
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
// 排序
Arrays.sort(nums1);
Arrays.sort(nums2);
if (nums1[nums1.length - 1] < nums2[0] || nums2[nums2.length - 1] < nums1[0]) {
return null;
}
// 定义双指针
int i = 0;
int j = 0;
// 返回结果。数组的长度最多应该是Math.min(num1, nums2)
int[] res = new int[nums1.length + nums2.length];
// 实际长度
int idx = 0;
for (int len1 = nums1.length, len2 = nums2.length; i < len1 && j < len2;) {
if (nums1[i] < nums2[j]) {
int start = nums1[i];
while (++i < len1) {
if (nums1[i] > start) {
break;
}
}
} else if (nums1[i] == nums2[j]) {
res[idx++] = nums1[i];
while (++i < len1) {
if (nums1[i] != nums1[i - 1]) {
break;
}
}
while (++j < len2) {
if (nums2[j] != nums2[j - 1]) {
break;
}
}
} else {
int start = nums2[j];
while (++j < len2) {
if (nums2[j] != start) {
break;
}
}
}
}
return Arrays.copyOfRange(res, 0, idx);
}
}