카테고리 없음
[LeetCode] Merge Intervals
제이G
2023. 4. 15. 12:45
리뷰
제한된 시간복잡도 O(N)을 만족하기 위해 정렬을 사용해야하는 문제.
제한된 시간복잡도를 만족하기 위해 어떻게 시간복잡도를 줄일 수 있는지 생각하는게 중요.
소요시간: 1시간
오래걸린이유: 합쳐지는 경우 인덱스 갱신 부분에서 코드 오류. 디버깅에 시간 소요.
문제 풀이
제한
- 배열의 개수: 1~10,000 → O(N)까지 가능
유형
Goal: 겹치는 배열들을 모두 합치고, 최종적으로 겹치지 않는 모든 배열 i들의 [Si, Ei]를 출력
→ 시간복잡도를 고려한 구현문제
설계
1. Intervals 배열 start 오름차순 기준 정렬
∵ 한 번의 배열 탐색으로 O(N)만에 끝내기 위함
2. 배열 합치기
- 합쳐지는 경우 갱신 (targetStart <= compareStart <= targetEnd)
[Si(targetStart), Ei(targetEnd)]의 Ei 갱신 - 안 합쳐지는 경우
갱신해둔 [Si(targetStart), Ei(targetEnd)]를 기록
구현
class Solution {
//O(NlogN)
public int[][] merge(int[][] intervals) {
sortByStartAscending(intervals); //O(NlogN)
List<int[]> answer = pro(intervals); //O(N)
return getAnswer(answer);
}
private void sortByStartAscending(int[][] intervals) {
Arrays.sort(intervals, (o1, o2) -> o1[0] - o2[0]);
}
private int[][] getAnswer(List<int[]> answer) {
int[][] ans = new int[answer.size()][2];
for(int idx=0; idx<ans.length; idx++) {
ans[idx][0] = answer.get(idx)[0];
ans[idx][1] = answer.get(idx)[1];
}
return ans;
}
//O(N)
private List<int[]> pro(int[][] intervals) {
List<int[]> answer = new ArrayList<>();
int targetIdx = 0;
while(targetIdx < intervals.length) {
int[] target = intervals[targetIdx];
targetIdx = mergeOverlapping(target, targetIdx+1, intervals, answer);
}
return answer;
}
//return: 최초로 안합쳐진 배열의 idx
private int mergeOverlapping(int[] target, int compareStartIdx, int[][] intervals, List<int[]> answer) {
int targetStart = target[0];
int targetEnd = target[1];
for(int compareIdx=compareStartIdx; compareIdx<intervals.length; compareIdx++) {
int[] compare = intervals[compareIdx];
if(isOverlapping(targetStart, targetEnd, compare)) { //합쳐지는 경우 -> targetEnd 갱신하고 다음 compare 진행
if(compare[1] > targetEnd) {
targetEnd = compare[1];
}
} else { //안합쳐지는 경우 -> 기록
answer.add(new int[] {targetStart, targetEnd});
return compareIdx;
}
}
// 마지막까지 다 합쳐진 경우 -> targetEnd 갱신하고 리턴
if(intervals[intervals.length-1][1] > targetEnd) {
targetEnd = intervals[intervals.length-1][1];
}
answer.add(new int[] {targetStart, targetEnd});
return intervals.length;
}
private boolean isOverlapping(int targetStart, int targetEnd, int[] compare) {
return targetStart <= compare[0] && compare[0] <= targetEnd;
}
}