티스토리 뷰

반응형

 

프로그래머스 - 실패율

 

이 문제와 비슷한 유형의 문제를 푼 적이 있어서 그런 식으로 풀었다가 시간 초과 났다.. 지금 보니까 배열을 자르고 넣고 자르고 넣고 아주 많은 연산을 해버렸다..

 

 


 

작성 답안

 

내가 푼 풀이이다. 몇몇 테스트 케이스는 통과도 안되었고 무엇보다 성능이 좋지 않다. while문에서 크게 처리시간을 잡아먹었다. 

또 실패율이 같을 때는 스테이지가(index) 작은 것부터 출력해야 되었던 부분에서 잘못 파고든 것 같다.

현재 스테이지와 스테이지에 도달한 플레이어를 나누는 부분에서 stage를 뜻하는 index i를 넣어주는 게 포인트였다.  나는 그 i 를 구하려고 index라는 변수를 새로 선언했는데 전혀 그럴 필요가 없었다.  sort() 비교함수에서 그 조건들을 이미 만족시켜 반환해주기 때문이다. 

 

하려고했던 방향..출력은 되나 효율적이지 못하다.

// stage = [1,2,3, 4, 5]
let index = [1, 2, 3, 4, 5];
let failRate = [2, 1, 5, 2, 3];
// 3 5 1 4 2

//2 3 4   5   1
1, 5, 2, 3, 2;

//3  4  5  1  2
5, 2, 3, 2, 1; // result.push(index.shif())  result = [3]

//4  5  1  2
2, 3, 2, 1;

//5  1  2  4
3, 2, 1, 2; //  result.push(index.shif())   result = [3, 5]

//1  2  4
2, 1, 2; //  result.push(index.shif())   result = [3, 5, 1]

//2  4
1, 2;

//4  2
2, 1; //  result.push(index.shif())   result = [3, 5, 1, 4]

// 2
1; //  result.push(index.shif())   result = [3, 5, 1, 4, 2]
// 2341

 

function solution(N, stages) {
  let answer = [];
  
  const curStageCount = [];
  const curSuccessCount = [];
  for (let i = 1; i <= N; i++) {
    curStageCount.push(stages.filter((v) => v === i).length);
    curSuccessCount.push(stages.filter((v) => v >= i).length);
  }

  const failRate = curStageCount.map(
    (item, index) => item / curSuccessCount[index]
  );

  let index = Array.from({ length: failRate.length }, (_, i) => i + 1);

  let first = failRate[0];
  
  while (true) {
    if (failRate.length === 0) break;
    first = failRate[0];
    if (first >= Math.max(...failRate)) {
      failRate.shift();
      answer.push(index.shift());
    } else {
      failRate.push(failRate.shift());
      index.push(index.shift());
    }
  }
  return answer;
}

 

 

 

수정 답안 

정렬을 이용하면 이렇게 간단해진다. 

반목 문안에서 curSuccessCount === 0 일 때 failRate: 0을 줌으로써 

textcase가 solution(5, [1, 1, 1, 1]) 일때처럼  NaN이 나오는 것을 방지 할 수 있다. 
 
 
function solution(N, stages) {
  let answer = [];

  for (let i = 1; i <= N; i++) {
    let curStageCount = stages.filter((v) => v === i).length;
    let curSuccessCount = stages.filter((v) => v >= i).length;
    if (curSuccessCount === 0) {
      answer.push({ stage: i, failRate: 0 });
      continue;
    }
    answer.push({ stage: i, failRate: curStageCount / curSuccessCount });
  }

  answer.sort((a, b) => b.failRate - a.failRate);
  return answer.map((x) => x.stage);

}

 

 

인수의 값이 같을 때의 정렬 방식

같은 값일 때는 sort()에서 어떻게 작동하지?라는 궁금증이 들어 찾아보았다. 

보통 sort()로 오름차순, 내림차순을 쓸 때  이런 식으로 간략하게 표현했지만 사실 이는 양수, 음수 또는 0을 반환하며 비교해주는 비교 연산을 간략하게 줄인 것이다. 

  answer.sort((a, b) => b.failRate - a.failRate);

 

 

그래서 아래와 같은 표현으로 비교 함수를 사용할 수 있다. 비교 함수의 반환값이 0보다 작으면(retun -1) 비교함수의 첫 번째 인수를 우선 정렬하고, 0보다 크면 두 번째 인수를 우선하여 (return 1) 정렬한다. 그리고 0이라면 정렬하지 않는다. 

값이 같은 경우는 0을 리턴하기 때문에 정렬되지 않는 것이고(유지의 개념) 이런 원리에 의해 index가 작은 것부터 출력이 되는 것이다. 

answer.sort((a, b) => {
    if (a.failRate > b.failRate) return -1;
    if (a.failRate < b.failRate) return 1;

    return 0;
  });

 

 


 

 

전체 답안 

sort() 비교함수에 대해 더 잘 알 수 는 문제였다 . 

function solution(N, stages) {
  let answer = [];

  const failRate = [];

  for (let i = 1; i <= N; i++) {
    let curStageCount = stages.filter((v) => v === i).length;
    let curSuccessCount = stages.filter((v) => v >= i).length;
    if (curSuccessCount === 0) {
      answer.push({ stage: i, failRate: 0 });
      continue;
    }
    answer.push({ stage: i, failRate: curStageCount / curSuccessCount });
  }

  answer.sort((a, b) => b.failRate - a.failRate);
  return answer.map((x) => x.stage);

}

 

 

 

반응형