이번 문제는 풀다가 시간이 너무 오래 걸릴것 같고 못풀겠어서 결국엔 다른 사람들의 풀이과정을 보고 나만의 풀이과정으로 만들었다. 근데 사실상 똑같다
레벨 1짜리였는데 못풀었다... 큰일이다.
그래도 이번 과정을 통해서 느끼고 배운점이 있을테니까 절대 손해는 아니다.
일단 문제부터 보자.
문제 설명
점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.
전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.
제한사항
- 전체 학생의 수는 2명 이상 30명 이하입니다.
- 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
- 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
- 여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.
- 여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.
입출력 예
n | lost | reserve | return |
5 | [2, 4] | [1, 3, 5] | 5 |
5 | [2, 4] | [3] | 4 |
3 | [3] | [1] | 2 |
입출력 예 설명
예제 #1
1번 학생이 2번 학생에게 체육복을 빌려주고, 3번 학생이나 5번 학생이 4번 학생에게 체육복을 빌려주면 학생 5명이 체육수업을 들을 수 있습니다.
예제 #2
3번 학생이 2번 학생이나 4번 학생에게 체육복을 빌려주면 학생 4명이 체육수업을 들을 수 있습니다.
나는 처음에 이 풀이를 lost 배열과 reserve배열에 접근하는것으로 수를 구하려고 했다.
하지만 그렇게 하다보니 문제가 풀리지 않았다.
그래서 다른 사람들의 풀이를 보니 다들 일단 전체 학생 수만큼의 배열을 생성해서 해당 배열에서 잃어버린 도난 당한 사람의 수를 빼고 여벌있는 사람들의 수를 더해서 계산을 했다.
그래서 그걸 보고 나도 일단은 학생수만큼 배열을 만들고 해당 배열에 1씩을 넣어줬다.
for(int i = 0; i<n;i++) {
all[i] = 1;
}
System.out.println("처음 : "+Arrays.toString(all));
그리고 여벌이 있는 사람들은 아래와 같이 하여 옷의 수를 1씩 더했다.
for(int i : reserve) {
all[i-1] += 1;
}
System.out.println("여벌 : "+Arrays.toString(all));
그리고 마지막으로 도난 당한 사람의 옷을 1씩 빼줬다.
for(int i : lost) {
all[i-1] -=1;
}
System.out.println("도난후 : "+Arrays.toString(all));
그럼 이제 내가 해야할것은 체육복이 2개 있는 사람이 +-1 인 사람중 한사람을 택하여서
체육복을 주면 된다.
그래서 위의 과정은 아래와 같이 만들었다.
for(int i = 0; i<all.length;i++) {
if(all[i] == 2) { //여벌 있는 애라면 진입
//여벌 +-1에 0인에 있으면 해당 친구 옷준다.
if(i!=0 && all[i-1] == 0 ) { //i가 0일때 에러
all[i] -=1;
all[i-1] +=1;
i-=1;
continue;
}
if(i!=n-1 && all[i+1] == 0) { //i가 n-1일때 에러
all[i] -=1;
all[i+1] +=1;
i -=1;
continue;
}
}
}
i-=1을하고 continue 한 이유는 아래와 같은 상황일때
int n = 5;
int[] lost = {1,3,5};
int[] reserve = {2,4,5};
2개인 사람이 다 본인것도 퍼주게 된다. 그래서 위의 상황을 방지하기 위해서 한번 체육복을 빌려주게 되면
다시 이전으로 돌아가 2인 사람들의 것만을 나눠주게 되는것이다.
전체 소스는 아래와 같다.
public static void main(String[] args) {
// TODO Auto-generated method stub
PreTest p = new PreTest();
int n = 5;
int[] lost = {1,3,5};
int[] reserve = {2,4,5};
System.out.println(p.solution(5,lost,reserve));
}
public int solution(int n, int[] lost, int[] reserve) {
int answer = 0;
int[] all = new int[n];
for(int i = 0; i<n;i++) {
all[i] = 1;
}
System.out.println("처음 : "+Arrays.toString(all));
for(int i : reserve) {
all[i-1] += 1;
}
System.out.println("여벌 : "+Arrays.toString(all));
for(int i : lost) {
all[i-1] -=1;
}
System.out.println("도난후 : "+Arrays.toString(all));
for(int i = 0; i<all.length;i++) {
if(all[i] == 2) { //여벌 있는 애라면 진입
//여벌 +-1에 0인에 있으면 해당 친구 옷준다.
if(i!=0 && all[i-1] == 0 ) { //i가 0일때 에러
all[i] -=1;
all[i-1] +=1;
}
if(i!=n-1 && all[i+1] == 0) { //i가 n-1일때 에러
all[i] -=1;
all[i+1] +=1;
}
}
}
System.out.println("나눔후 : "+Arrays.toString(all));
for(int i : all) {
if(i >= 1)
answer++;
}
return answer;
}
느낀점
1. 문제의 상황대로 차근차근 코딩을 풀어나가면 충분히 해결할수있다.
'코딩일기 > 알고리즘' 카테고리의 다른 글
[프로그래머스 : 레벨2] 큰 수 만들기 :Stack (Java) (0) | 2021.06.11 |
---|---|
[프로그래머스 : 레벨 2] 조이스틱 : 탐욕알고리즘 (Java) (0) | 2021.06.11 |
[프로그래머스 : 레벨 2] 카펫 (java) (0) | 2021.06.08 |
[프로그래머스 : 레벨2] 소수 찾기 : 재귀호출 (Java) (0) | 2021.06.08 |
[프로그래머스 : 레벨1] 모의고사 (Java) (0) | 2021.06.08 |