function solution(N, stages) {
// 스테이지별 실패자 수 ({ 스테이지: 실패자 수 })
let failCountObj = {};
for (let i = 1; i <= N; i++) {
failCountObj[i] = 0;
for (let x of stages) {
if (x === i) failCountObj[i]++;
}
}
// 스테이지별 실패율 ({ 스테이지: 실패율 })
let failRateObj = {};
let failCountValues = Object.values(failCountObj);
let currentCount = stages.length;
for (let i = 0; i < failCountValues.length; i++) {
let failRate = failCountValues[i] / currentCount; // 실패율
failRateObj[i + 1] = failRate; // 스테이지별 실패율 추가
currentCount -= failCountValues[i]; // (판단 후) 남은 인원
}
let stageKeys = Object.keys(failRateObj); // 스테이지
// 스테이지를 실패율 기준으로 내림차순 정렬
// 실패율이 같을 경우 스테이지를 기준으로 오름차순 정렬
stageKeys.sort((a, b) => failRateObj[a] === failRateObj[b] ? failRateObj[a] - failRateObj[b] : failRateObj[b] - failRateObj[a])
return stageKeys.map((key) => key * 1);
}
빈 객체에 key: value를 추가할 때는 먼저 key를 초기값과 함께 셋팅해주어야 한다. 그래야 value 자리에 값을 추가할 수 있다 😃
스테이지별 실패율
객체를 구할 때 처음에는 { 실패율: 스테이지 }
로 구했다가 실패율이 같은 경우 key의 특성 상 하나의 key에 계속 등록이 되어서 { 스테이지: 실패율 }
형태로 다시 바꿔서 풀었다.
코드를 최대한 줄이기 위해 for문에서 나오는 인덱스를 스테이지로 간주했고, 맨 아래 sort문을 if문으로 풀고 난 뒤 삼항 연산자로 리팩토링했다. (풀 때는 각 요소 부분이 길어서(failRateObj[a])인지 if문이 덜 헷갈렸다..)
처음에 주어진 answer 변수와 마지막 return answer문도 없애고, 정렬한 stageKeys(변수명 그냥 stages로 하고 싶었으나 함수 첫 인자에 stages..)에서 map으로 새 배열을 만들어 바로 반환했다. (여기서 parseInt 대신 * 1을 써서 숫자화)
고민을 2-3시간 정도 했는데 점수가 11점이나 떴다 🥳 (맨날 1점, 3점 뜨다가..) 혼자 풀어서 이렇게 높은 점수 얻은 건 처음이라 기념으로 캡쳐
function solution(N, stages) {
let result = [];
for(let i = 1; i <= N; i++){
let reach = stages.filter((x) => x >= i).length;
let curr = stages.filter((x) => x === i).length;
result.push([i, curr/reach]);
}
result.sort((a,b) => b[1] - a[1]);
return result.map((x) => x[0]);
}
음.. 강호에 고수는 많다.. 분자와 분모를 구하는 로직을 객체, 배열 전환 없이 filter로 간결하게 처리했다.
남은 인원(reach)을 단순히 뺄셈('-')이 아니라 현재 인덱스(스테이지)보다 큰 사람의 수(length)를 세서 구했고, 현재 스테이지의 실패자 수(curr)는 스테이지와 같은 숫자인 인원 수를 셌다.
즉, 굳이 뺄셈을 하며 기존 배열을 수정할 필요 없이 단순히 조건에 맞는 사람 수를 세면 되는 거였다.
이 부분은 남은 인원 수가 stage와 연관이 있어서 가능했던 것 같다. 최대한 기존에 있는 것을 이용해야 한다는 규칙을 떠올림
마지막의 sort b[1] - a[1]
는 직접 코드를 쳐 보고 이해했다. 위의 for문에서 result에 배열을 추가하여 결과적으로 2차원 배열이 되었기 때문이다.
[[스테이지, 실패율], [스테이지, 실패율]...] 이라는 형태가 나오니 마치 객체로 { 스테이지: 실패율, ... } 형태를 만들어준 것과 비슷했다.
각 배열의 1번째 항 실패율에 맞게 내림차순 정렬을 해주고, return 문에서는 각 배열의 0번째 값 스테이지를 뽑아 새 배열을 반환했다.
이렇게 2차원 배열을 반복문에 쓰지 않는다면(시간복잡도 O(N2) = 헬) '정렬 후에 a에 해당하는 b'가 필요할 때 객체 대신 2차원 배열을 쓰는 것도 좋은 방법인 것 같다.
많은 걸 배울 수 있는 풀이였다 👊