알고리즘 문제풀이 - 복서 정렬하기

공부중인 개발자·2021년 9월 6일
0

알고리즘

목록 보기
9/63
post-thumbnail

https://programmers.co.kr/learn/courses/30/lessons/85002

복서 정렬하기

문제 설명

복서 선수들의 몸무게 weights와, 복서 선수들의 전적을 나타내는 head2head가 매개변수로 주어집니다. 복서 선수들의 번호를 다음과 같은 순서로 정렬한 후 return 하도록 solution 함수를 완성해주세요.

전체 승률이 높은 복서의 번호가 앞쪽으로 갑니다. 아직 다른 복서랑 붙어본 적이 없는 복서의 승률은 0%로 취급합니다.
승률이 동일한 복서의 번호들 중에서는 자신보다 몸무게가 무거운 복서를 이긴 횟수가 많은 복서의 번호가 앞쪽으로 갑니다.
자신보다 무거운 복서를 이긴 횟수까지 동일한 복서의 번호들 중에서는 자기 몸무게가 무거운 복서의 번호가 앞쪽으로 갑니다.
자기 몸무게까지 동일한 복서의 번호들 중에서는 작은 번호가 앞쪽으로 갑니다.

제한사항

weights의 길이는 2 이상 1,000 이하입니다.
weights의 모든 값은 45 이상 150 이하의 정수입니다.
weights[i] 는 i+1번 복서의 몸무게(kg)를 의미합니다.
head2head의 길이는 weights의 길이와 같습니다.
head2head의 모든 문자열은 길이가 weights의 길이와 동일하며, 'N', 'W', 'L'로 이루어진 문자열입니다.
head2head[i] 는 i+1번 복서의 전적을 의미하며, head2head[i][j]는 i+1번 복서와 j+1번 복서의 매치 결과를 의미합니다.
'N' (None)은 두 복서가 아직 붙어본 적이 없음을 의미합니다.
'W' (Win)는 i+1번 복서가 j+1번 복서를 이겼음을 의미합니다.
'L' (Lose)는 i+1번 복사가 j+1번 복서에게 졌음을 의미합니다.
임의의 i에 대해서 head2head[i][i] 는 항상 'N'입니다. 자기 자신과 싸울 수는 없기 때문입니다.
임의의 i, j에 대해서 head2head[i][j] = 'W' 이면, head2head[j][i] = 'L'입니다.
임의의 i, j에 대해서 head2head[i][j] = 'L' 이면, head2head[j][i] = 'W'입니다.
임의의 i, j에 대해서 head2head[i][j] = 'N' 이면, head2head[j][i] = 'N'입니다.

입출력 예

weightshead2headresult
[50,82,75,120]["NLWL","WNLL","LWNW","WWLN"][3,4,1,2]
[145,92,86]["NLW","WNL","LWN"][2,3,1]
[60,70,60]["NNN","NNN","NNN"][2,1,3]

입출력 예 설명

입출력 예 #1

다음은 선수들의 정보를 나타낸 표입니다.

선수 번호vs 1번vs 2번vs 3번vs 4번승률자기보다 무거운 복서를 이긴 횟수몸무게
1번-패배승리패배33.33%1회50kg
2번승리-패배패배33.33%0회82kg
3번패배승리-승리66.66%2회75kg
4번승리승리패배-66.66%0회120kg

본문에 서술된 우선순위를 따라 [3,4,1,2] 를 return 합니다.
입출력 예 #2

다음은 선수들의 정보를 나타낸 표입니다.

선수 번호vs 1번vs 2번vs 3번승률자기보다 무거운 복서를 이긴 횟수몸무게
1번-패배승리50%0회145kg
2번승리-패배50%1회92kg
3번패배승리-50%1회86kg

본문에 서술된 우선순위를 따라 [2,3,1] 을 return 합니다.
입출력 예 #3

다음은 선수들의 정보를 나타낸 표입니다.

선수 번호vs 1번vs 2번vs 3번승률자기보다 무거운 복서를 이긴 횟수몸무게
1번---0%(무전적)0회
2번---0%(무전적)0회
3번---0%(무전적)0회

본문에 서술된 우선순위를 따라 [2,1,3] 을 return 합니다.

먼저 문제를 풀기 전에 착각을 해서 한참동안 이상하게 문제를 풀었다.
해당 인덱스(선수)의 등수를 나열해야한다고 생각했다.(예제1번이 정확하게 같다 ㅠㅠ ㅋㅋㅋ)
그래서 예제 2번이 계속 [3,1,2] 가 나왔고 질문 결과 등수가 [1,1,1] 에서 조건이 안맡는 사람의 랭크가 떨어지는 것이 아닌
[1,2,3] 순서가 정렬됐을 때 조건에 맞춰서 배열안의 요소들을 정렬시켜주는 것이었다.

function solution(weights, head2head) {
  var answer = [];
  let n = weights.length;
  let person = weights.map((el, i) => {
    return { index: i, weight: el, winOver: 0, winRate: 0 };
  });
	// 승률과 체중미만 승리 구하기
  for (let i = 0; i < n; i++) {
    let totalCount = 0;
    let winCount = 0;
    for (let j = 0; j < n; j++) {
      if (head2head[i][j] === "W") {
        winCount++;
        if (weights[i] < weights[j]) person[i]["winOver"] += 1;
      }
      if (head2head[i][j] !== "N") totalCount++;
    }
    totalCount === 0
      ? (person[i]["winRate"] = 0)
      : (person[i]["winRate"] = winCount / totalCount);
  }
    // 정렬
    person = person.sort((a,b) => {
        if(a.winRate !== b.winRate) {
            return b.winRate - a.winRate
        }
        else {
            if(a.winOver !== b.winOver) {
                return b.winOver - a.winOver
            }
            else {
                if(a.weight !== b.weight) {
                    return b.weight - a.weight
                }
                else {
                    return a.index - b.index
                }
            }
        }
    })
    console.log(person)
  person.forEach(el => answer.push(el.index+1))

  return answer;
}

문제를 여러번 다시 만졌지만 내가 해왔던대로 안전하게 문제를 해결해야겠다고 생각해서 if와 else를 이용하여 sort 공식을 만들었다.
다른 사람들의 풀이를 보니까 삼항연산자를 기가 막히게 잘쓰는 모습을 보고 많이 연습해야겠다는 생각이 든다.

일단 문제 풀이의 경우 먼저 person 이라는 배열의 요소는 객체로 안에 인덱스, 몸무게, 체중미만 승리, 승률 네가지의 키가 있게 설정 한 뒤 각각의 값을 찾아서 넣어줬다.

그리고 sort로 비교 값이 같지 않을 경우와 같을 경우 두개로 나누고 같지 않을 경우에는 내림차순 같을 경우에는 다음 조건으로 넘어가는 것으로 처리했다. 마지막 조건의 경우 오름차순 인덱스를 이용했다.
인덱스는 0부터 시작인데 선수 넘버는 1부터 시작이므로 정답에 넣어줄 때 +1 씩해줘서 넣어주게 됐다.

문제를 조금 더 세련되게 풀어보고 싶다.

profile
열심히 공부하자

0개의 댓글