함께 쓰는 습관을 들이세요! "너겟 데일리 뉴플랜 · 4월 업데이트 챌린지" 참여 12일차 입니다. 클릭하시면 이벤트 내용을 보실 수 있습니다 .
주제
350. 두 배열의 교차 II
두 정수 배열 의 nums1
합 이 주어지면 nums2
두 배열의 교집합을 배열로 반환하십시오. 반환된 결과에서 각 요소의 발생 횟수는 해당 요소가 두 배열에 모두 나타나는 횟수와 같아야 합니다(발생 횟수가 일치하지 않으면 더 작은 값으로 간주됨). 출력 결과의 순서는 무시할 수 있습니다.
예 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
复制代码
예 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
复制代码
힌트:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
复制代码
고급: 주어진 배열이 이미 정렬되어 있으면 어떻게 됩니까? 알고리즘을 어떻게 최적화하시겠습니까?
nums1의 크기가 nums2보다 작은 경우 어떤 방법이 더 낫습니까?
nums2의 요소가 디스크에 저장되어 있고 메모리가 제한되어 있으며 모든 요소를 한 번에 메모리에 로드할 수 없는 경우 어떻게 해야 합니까?
답변
문제 해결 분석
문제 해결 아이디어
- 아이디어: 두 배열을 정렬한 다음 이중 포인터를 사용하여 두 배열의 교차점을 얻습니다.
- 먼저 정렬한 다음 이중 포인터로 두 배열을 반복합니다.
- 처음에는 두 포인터가 각각 배열의 헤드를 가리킵니다. 한 번에 두 포인터의 두 숫자를 비교합니다.
- 두 숫자가 같지 않으면 더 작은 숫자에 대한 포인터가 오른쪽으로 1만큼 이동하고,
- 두 숫자가 같으면 해당 숫자를 답에 추가하고 두 포인터를 하나씩 오른쪽으로 이동합니다.
- 하나 이상의 포인터가 배열의 경계를 초과하면 탐색이 종료됩니다.
복잡성
시간 복잡도 O(N)
공간 복잡도 O(|Σ|)
문제 해결 코드
솔루션 코드는 다음과 같습니다(코드의 자세한 설명).
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
// 1. 排序
Arrays.sort(nums1);
Arrays.sort(nums2);
int length1 = nums1.length, length2 = nums2.length;
int[] intersection = new int[Math.min(length1, length2)];
int index1 = 0, index2 = 0, index = 0;
// 2. 两个指针 index1, index2
while(index1 < length1 && index2 < length2) {
if (nums1[index1] < nums2[index2]) {
index1++;
} else if (nums1[index1] > nums2[index2]) {
index2++;
} else {
intersection[index] = nums1[index1];
index1++;
index2++;
index++;
}
}
return Arrays.copyOfRange(intersection, 0, index);
}
}
复制代码
제출 후 피드백 결과(이 주제는 최적화되지 않았기 때문에 성능은 평균입니다):