n
명이 있는 교실에는 체육복을 도난당한 그룹lost
와 여분의 체육복을 가진 그룹reserve
이 주어진다. 체육복의 등 뒤에는 숫자가 써져있으며, 여분을 가진 학생은 자신의 번호 앞 혹은 뒤 학생에게만 체육복을 빌려줄 수 있다.
이 때 수업을 들을 수 있는 최대한 많은 학생의 수는 몇인가?
n | lost | reserve | return |
---|---|---|---|
5 | [2,4] | [1,3,5] | 5 |
5 | [2,4] | [3] | 4 |
6 | [1,5,6] | [1,2,3,5] | 5 |
1) 도난 그룹과 여분을 가진 그룹을 오름차순으로 정렬한다.
2) 도난을 당한 학생 중 여분을 가진 학생의 수를 먼저 계산한다.
3) 도난을 당한 학생 중 여분을 갖지 못한 학생의 수를 계산한다.
O(nlogn)
import java.util.*;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
int answer = n - lost.length;
Arrays.sort(lost);
Arrays.sort(reserve);
// 선택 절차 : 각 배열을 오름차순으로 정렬한다
for(int i=0;i<lost.length;i++) {
for(int j=0;j<reserve.length;j++) {
if (lost[i] == reserve[j]) {
answer++;
reserve[j] = -1;
lost[i] = -1;
break;
}
}
}
// 도난당한 학생 중 여벌이 있는 학생 수 계산
for(int i=0;i<lost.length;i++) {
for(int j=0;j<reserve.length;j++) {
if (lost[i] == reserve[j]-1 || lost[i] == reserve[j]+1) {
answer++;
reserve[j] = -1;
break;
}
}
}
// 도난당한 학생 중 여벌이 없는 학생 수 계산
return answer;
}
}
- 위의 알고리즘 설계와 같은 코드이지만, 전체 학생의 체육복 현황을 관리함으로서 반복문의 중첩을 줄일 수 있다.
- 시간복잡도 이 되게 된다.
state
배열에 저장되는 각각의 값은 다음을 의미한다.
-1
: 도난당한 학생 = 참가 불가0
: 여벌은 없지만, 자신의 체육복을 지닌 학생 = 참가 가능1
: 여벌이 있는 학생 = 참가 가능- 여벌을 받을 수 없는 학생이 있는 경우, 전체 학생 수에서
-1
을 진행하여 최종 결과값을 반환한다.
import java.util.*;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
int answer = n;
int[] state = new int[n];
for(int l : lost)
state[l-1]--;
for(int r : reserve)
state[r-1]++;
// 도난당한 학생 중 여벌이 있는 학생 계산
for(int i=0;i<n;i++) {
if (state[i]==-1) {
if (i-1>=0 && state[i-1]==1) {
state[i]++;
state[i-1]--;
} else if (i+1<n && state[i+1] == 1) {
state[i]++;
state[i+1]--;
} else {
answer--;
}
}
}
// 도난당한 학생 중 여벌이 없는 학생 계산
return answer;
}
}