프로그래머스 | 가장 큰 수

chaen·2024년 2월 10일
post-thumbnail

📌 문제

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

제한 사항

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

입출력 예

numbersreturn
[6, 10, 2]"6210"
[3, 30, 34, 5, 9]"9534330"

✨ 해결 방법

numbers를 최대 자리 수가 가장 큰 수부터 정렬하는 것이 관건입니다. 이때, 단순히 이렇게만 정렬하는 것이 아니라 두 수를 합쳤을 때 어떤 경우가 더 큰지 또한 비교해야 합니다. (30, 3, 34가 있을 때, 34, 30, 3 이 아닌 34, 3, 30이 되도록)
이후 정렬된 순서에 맞춰 차례대로 문자열을 합쳐서 정답을 도출합니다.

💻 solution 1

function solution(numbers) {
    const nums = numbers.sort((a, b)=>(String(b) + String(a) >= String(a) + String(b) ? 1 : -1));
    return nums[0] === 0 ? '0' : nums.reduce((acc, cur) => acc + cur.toString(), "");
}

정렬 시 주의할 점 1

numberssort().reverse() 할 경우 문자열은 단순히 최대 자리 수가 가장 큰 순으로 정렬됩니다. 예를 들어 [3, 30, 34, 5, 9]가 있을 때, [ 9, 5, 34, 30, 3] 순으로 구성됩니다. 하지만 9534330이 9534303 보다 큰 수이기 때문에, 다른 방법을 사용하여 정렬할 필요가 있습니다.

위 코드에서는 두 식의 합을 비교합니다. 예를 들어 문자열 9와 5를 더한 95가, 5와 9를 더한 59보다 큰지 검사하고, 클 경우 그대로 두고 (1), 작을 경우 (-1) 두 수의 순서를 뒤바꾸는 구조를 갖습니다.

정렬 시 주의할 점 2

numbers가 '0' 으로만 구성될 경우를 고려해야 합니다. 위의 정렬 방법을 사용할 경우 다른 경우에서는 모두 올바르게 동작하지만, 0이 1개 이상 있을 경우 0000.... 으로 0의 합으로 문자열이 이루어집니다. 하지만 0만 있을 경우 결과값은 '0' 으로 끝나야 하기 때문에, 예외 처리가 필요합니다.
따라서 nums의 0번째 값이, 즉 가장 큰 값이 0이라면, '0'을 반환하고, 아니라면 reduce 식을 실행하도록 합니다.


위 두 가지 사항을 주의하여 reduce식을 전개해보면, 현재 인덱스의 값 cur을 문자열로 바꾼 값을 모두 합친 값인 acc에 누적하여 더하면 결과값이 나옵니다. 이때 초기값을 빈 배열 ""로 설정하면 오류 없이 알맞은 값을 도출할 수 있습니다.

💻 solution 2

function solution(numbers) {
    const nums = numbers.sort((a, b)=>(`${b}${a}` >= `${a}${b}` ? 1 : -1));
    return nums[0] === 0 ? '0' : nums.reduce((acc, cur) => acc + cur.toString(), "");
}

비슷한 형식이지만, 문자열로 바꾸는 대신 ${}을 통해 변수를 받는 방법도 있습니다.

0개의 댓글