[프로그래머스] Lv.1 체육복 JavaScript

Janet·2023년 3월 14일
0

Algorithm

목록 보기
73/314

문제 설명

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.

전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.

제한사항

  • 전체 학생의 수는 2명 이상 30명 이하입니다.
  • 체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.
  • 여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.
  • 여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.

입출력 예

nlostreservereturn
5[2, 4][1, 3, 5]5
5[2, 4][3]4
3[3][1]2

입출력 예 설명

예제 #11번 학생이 2번 학생에게 체육복을 빌려주고, 3번 학생이나 5번 학생이 4번 학생에게 체육복을 빌려주면 학생 5명이 체육수업을 들을 수 있습니다.

예제 #23번 학생이 2번 학생이나 4번 학생에게 체육복을 빌려주면 학생 4명이 체육수업을 들을 수 있습니다.


문제풀이

💡 문제풀이 과정

  • 주어진 2개의 배열 lostreserve로만 filter() 함수나 for() 반복문 includes() 메소드를 통해 이래저래 코드실행에선 통과를 했는데, 제출 후 채점에서는 정확도가 100%까지 나오지 않아서 fail을 반복했다…🤯
  • 그러다가 다른 사람들의 풀이를 구글링했는데, 그 중 1번 답안의 풀이가 가장 이해가 쉽고 코드가 명료해 보여서 좀 더 보기 편한 쪽으로 코드를 수정하였다. students라는 새로운 array를 만든다. 이 배열은 초기값 1로 채워진 배열로, 배열의 length는 n + 1로 만드는데 그 이유는 학생들의 번호가 1번부터 시작하기 때문이다. let students = Array(n + 1).fill(1);
  • 그 다음은 map()함수를 이용하여 students의 배열을 초기값 1에서, 분실한 학생의 경우 0으로, 여유 벌이 있는 학생은 2로 값을 변경해 준다. 본인 옷 1벌만 있는 학생은 초기값 1을 유지하게 된다.
lost.map((v) => students[v] = students[v] - 1);
reserve.map((v) => students[v] = students[v] + 1);
  • 마지막으로 다시 map()함수와 조건문을 사용하여 체육복이 0벌인 학생들이 2벌을 가지고 있는 학생들에게서 빌릴 수 있는지 확인하는 작업을 한다. students배열에서 0인 학생의 앞 번호 학생과 뒷 번호 학생이 2인지를 확인하여 체육복을 빌린다. 만약, 앞 번호 혹은 뒷 번호 모두에게 체육복을 빌리지 못한 학생은 체육 수업에 불참하게 되므로, 전체 학생 수에서 불참하게 되는 학생의 수를 제외하고 리턴한다.

  • 답안 2번의 경우는 다른 사람의 풀이를 보았는데, filter() 함수와 find() 및 절대값을 구하는 메소드인 Math.abs()를 사용하여 풀이하였다.

✅ 답안 #1

function solution(n, lost, reserve) {
  let absent = 0;
  let students = Array(n + 1).fill(1);
	//초기값 1로 채워진 array로, 학생들의 번호는 1번부터 시작하기에 length는 n+1

  lost.map((v) => students[v]--);
  reserve.map((v) => students[v]++);
	//분실: 0, 여유 벌 있음: 2 (디폴트 값: 1, 본인 옷 있는 학생)
  
  students.map((v, i) => {
    if (v === 0) { //분실인 경우
      if (students[i - 1] === 2) {
		//앞 번호 학생이 2벌인 경우 1벌 빌려줌
        students[i - 1]--;
        v++;
      } else if (students[i + 1] === 2) {
		//앞 번호 학생에게 못 빌리고, 뒷 번호 학생이 2벌인 경우 1벌 빌려줌
        students[i + 1]--;
        v++;
      } else absent++;
        //앞, 뒤 학생 모두에게 빌리지 못하여 수업 불참하는 학생 수
    }
  });
  return n - absent; //전체 학생 수 - 불참 학생 수
}

✅ 답안 #2

function solution(n, lost, reserve) {
  lost.sort((a, b) => a - b);
  reserve.sort((a, b) => a - b);

  const newLost = lost.filter((l) => !reserve.includes(l));
  let newReserve = reserve.filter((r) => !lost.includes(r));

  return (
    n - newLost.filter((a) => {
      const b = newReserve.find((r) => Math.abs(r - a) === 1);
      if (!b) return true;
      newReserve = newReserve.filter((r) => r !== b);
    }).length
  );
}
profile
😸

0개의 댓글