```
public int[] intersection(int[] nums1, int[] nums2) {
//special cases
if (nums1 == null || nums2 == null) {
return new int[0];
}
Arrays.sort(nums1);
Arrays.sort(nums2);
//save results
List<Integer> res = new ArrayList<Integer>();
int i = 0;
int j = 0;
while (i < nums1.length && j < nums2.length) {
if (nums1[i] < nums2[j]) {
++i;
} else if (nums1[i] > nums2[j]) {
++j;
} else {
res.add(nums1[i]);
++i;
++j;
}
//critical invariant: i and j both are the first elements of a duplicate region
while (i >=1 && i < nums1.length && nums1[i] == nums1[i-1]) {
++i;
}
while (j >=1 && j < nums2.length && nums2[j] == nums2[j-1]) {
++j;
}
}
//convert res list to an array
int[] output = new int[res.size()];
int k = 0;
for (int x : res) {
output[k++] = x;
}
return output;
}
```