https://school.programmers.co.kr/learn/courses/30/lessons/42862#
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
보기에는 쉬워보이나 예외 케이스가 많아서 생각이 많아지는 문제였다.
우선 오류가 생기는 코드부터 확인해보자.
우선 lost배열과 reserve배열을 비교하며 앞뒤 번호에 여분이 있는지만 체크를 해봤다.
import java.util.*;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
int answer = n-lost.length;
boolean[] extra = new boolean[reserve.length]; //빌려줘서 여벌이 없는지를 체크
boolean[] lostStudent = new boolean[lost.length]; //이미 빌려서 다시 빌릴필요가 없는 학생
for(int i=0; i<lost.length; i++){ //다른사람에게 여벌을 빌려주는 경우
for(int j=0; j<reserve.length; j++){
if(!lostStudent[i]){
if((lost[i]-1)==reserve[j]){
if(!extra[j]){
answer++;
extra[j]=true;
j=reserve.length;
}
}
else if((lost[i]+1)==reserve[j]){
if(!extra[j]){
answer++;
extra[j]=true;
j=reserve.length;
}
}
}
}
}
return answer;
}
}
이러면 오류가 생긴다.
위 코드는 문제의 중요한 요구사항을 놓쳐서 예외를 잘 처리하지 못한 코드이다.
요구사항에는 다음과 같은 사항이 존재한다.
여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.
즉, 여별의 체육복을 가져온 학생이 체육복을 도난당한 경우도 체크를 해줘야 한다.
import java.util.*;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
int answer = n-lost.length;
boolean[] extra = new boolean[reserve.length];
boolean[] lostStudent = new boolean[lost.length]; //이미 빌려서 다시 빌릴필요가 없는 학생
for(int i=0; i<lost.length; i++){ //여벌의 체육복을 가지고 왔는데 분실한 경우여벌의 체육복을 가지고 왔는데 분실한 경우
for(int j=0; j<reserve.length; j++){
if(lost[i]==reserve[j] && extra[j]==false){
extra[j]=true;
lostStudent[i]=true;
answer++;
j=reserve.length;
}
}
}
for(int i=0; i<lost.length; i++){ //다른사람에게 여벌을 빌려주는 경우
for(int j=0; j<reserve.length; j++){
if(!lostStudent[i]){
if((lost[i]-1)==reserve[j]){
if(!extra[j]){
answer++;
extra[j]=true;
j=reserve.length;
}
}
else if((lost[i]+1)==reserve[j]){
if(!extra[j]){
answer++;
extra[j]=true;
j=reserve.length;
}
}
}
}
}
return answer;
}
}
하지만 위 코드도 정답 코드는 아니다.
왜냐하면 아래와 같은 테스트 코드에서 잘못된 결과를 출력하기 때문이다.
위 코드에서는 결과가 4로 출력되지만
4번학생이 5번학생에게 빌리고, 2번학생은 3번학생에게 빌리면 모든 학생이 체육시간에 출석을 할 수 있게 된다.
이러한 예외를 잡기 위해서는 lost배열과 reserve배열이 정렬되도록 해야한다.
<정답코드>
import java.util.*;
class Solution {
public int solution(int n, int[] lost, int[] reserve) {
int answer = n-lost.length;
boolean[] extra = new boolean[reserve.length]; //이미 빌려줘서 다른사람에게 못 빌려주는 경우 체크
boolean[] lostStudent = new boolean[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] && extra[j]==false){
extra[j]=true;
lostStudent[i]=true;
answer++;
j=reserve.length;
}
}
}
for(int i=0; i<lost.length; i++){ //다른사람에게 여벌을 빌려주는 경우
for(int j=0; j<reserve.length; j++){
if(!lostStudent[i]){
if((lost[i]-1)==reserve[j]){
if(!extra[j]){
answer++;
extra[j]=true;
j=reserve.length;
}
}
else if((lost[i]+1)==reserve[j]){
if(!extra[j]){
answer++;
extra[j]=true;
j=reserve.length;
}
}
}
}
}
return answer;
}
}
2025년 3월 24일 풀이
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; //더이상 비교가 필요 없으므로 -1로 설정
lost[i]=-1;
j=reserve.length;
}
}
}
for(int i=0; i<lost.length; i++){
for(int j=0; j<reserve.length; j++){
if(lost[i]-1== reserve[j] || lost[i]+1 == reserve[j]){
answer++;
reserve[j]=-1;
j=reserve.length;
}
}
}
return answer;
}
}
'알고리즘 > 탐욕법(Greedy)' 카테고리의 다른 글
프로그래머스 - 섬 연결하기(Java) (1) | 2025.02.04 |
---|---|
신장트리(Spanning Tree), 최소신장 트리(Minimum Spanning Tree) (0) | 2025.02.04 |
프로그래머스 - 구명보트 (1) | 2025.02.02 |
프로그래머스 - 큰 수 만들기(Java) (0) | 2025.02.01 |