가장 큰 수 biggest number

💡
Level 2 210920
과거 내 풀이
function solution(numbers) {
    var answer = '';
//     answer = numbers
//         .map((num) => num.toString())
//         .sort((a, b) => b + a - (a + b))
//         .join("");


//     return answer.replace(/^0+/, "0");
        answer = numbers
        .map((num) => num.toString())
        .sort((a, b) => b + a - (a + b));

    // 모든 요소가 0인 경우에는 /^0+/를 이용해 판단하여 "0"만 리턴한다. reduce는 ""를 초깃값으로 요소를 차례대로 이어준다.
    return answer.reduce((acc, curr) => (acc + curr).replace(/^0+/, "0"), "");
}

문제 설명

0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요.
예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210입니다.
0 또는 양의 정수가 담긴 배열 numbers가 매개변수로 주어질 때, 순서를 재배치하여 만들 수 있는 가장 큰 수를 문자열로 바꾸어 return 하도록 solution 함수를 작성해주세요.

제한 사항

  • numbers의 길이는 1 이상 100,000 이하입니다.
  • numbers의 원소는 0 이상 1,000 이하입니다.
  • 정답이 너무 클 수 있으니 문자열로 바꾸어 return 합니다.

입출력 예

numbers
return
 

My solution


[6, 10, 2]의 배열에서 우리가 원하는 값을 만들어내려면 앞자리에 10이 아닌 6이 와야 한다. 배열을 그대로 join('')했을 때 가장 큰 수는 6210이 되어야 하기 때문이다.

이를 위해 sort 메서드의 compare function에서 a, b를 비교할 때 a = 6, b = 10을 비교하는 경우가 온다면 이를 6, 10의 위치로 유지하도록 해야할 것이다.

sort의 compare function을 잘 작성하는 것이 중요한 문제다. 이 함수는 아래와 같이 동작한다.
let arr = [21, 45, 9, 10, 15, 3];
 
function sort1(a, b) {
    return a-b;
}
 
arr.sort(sort1); // (6) [3, 9, 10, 15, 21, 45]
예를 들어 a는 21, b는 9이면 21-9=12 이므로 리턴값은 양수이다. 이 경우 b가 a와 위치가 서로 바뀌어 더 앞의 인덱스로 이동하게 된다.
리턴값이 음수인 경우는 a가 b보다 앞의 인덱스로 이동하게 된다.
리턴값이 0이면 그대로 유지한다.

 
a와 b의 값 중에 a값이 앞으로 이동하게 하기 위한 조건은 a="6", b="10"일 때 a+b = "610", b+a = "106"으로 두 숫자문자열을 더해주어 계산하면 해결할 수 있다.
계산한 값이 양수면 뒤에 있어야 할 b가 앞으로 이동하기 때문에 값이 음수가 되게 하려면
b+a - (a+ b)가 된다.
[0, 10, 2]를 예로 들면, a가 "0", b가 "10"인 경우, a+b = "010", b+a = "100"이 된다. 이 경우 b가 앞에 있는 것이 더 큰 수를 만들어준다.
위의 식으로 계산하면 b+a - (a+b) = "100" - ("010") = 90이 된다. 양수이므로 b는 앞으로 이동한다.
또한, [1000, 300]에서 b+a - (a+b) = "300"+"1000" - ("1000"+"300") = "3001000" - "1000300" = 2000700으로 양수이므로 b("300")가 앞으로 이동한다.
두 개의 원소를 가진 배열에서 숫자를 이어 더 큰 숫자를 판단하는 조건에 따라 compare function을 짜면 numbers의 원소의 개수가 더 늘어나더라도 같은 결과를 얻을 수 있었다.
하나 더 유의해야할 것은 numbers에 0이 들어오게 되면 0을 이어서 만든 "000"과 같은 리턴값이 나타날 수 있다는 것이다. 0이 반복되는 문자열을 걸러내기 위해 아래의 코드를 작성하였다.
notion image
return answer[0] === "0" ? "0" : answer;
 

소스 코드

function solution(numbers) {
    let answer = numbers
        .map((v) => v.toString())
        .sort((a, b) => b + a - (a + b))
        .join("");
    return answer[0] === "0" ? "0" : answer;
}

test("solution", () => {
    expect(solution([6, 10, 2])).toBe("6210");
    expect(solution([3, 30, 34, 5, 9])).toBe("9534330");
    expect(solution([0, 0, 0])).toBe("0");
});