[Leetcode] 172 - Factorial Trailing Zeroes

coderH·2023년 6월 18일
0

LeetCode

목록 보기
1/1

문제

n이라는 숫자가 주어졌을 때, n 팩토리얼의 결과값에서 뒤쪽에 위치한 연속된 0의 개수를 반환하세요.

제한 사항

  • 0 <= n <= 10^4

입출력 예

nresult
30
51
00

정답

const factorial = (n) => {
    let num = BigInt(1);

    while (n > 1) {
        num = num * BigInt(n);
        n -= 1;
    }

    return num;
}

const trailingZeroes = (n) => {
    const num = factorial(n);

    if (num > 9) {
        const zeros = String(num).match(/0*0$/);
        return zeros ? zeros[0].length : 0;
    }

    return 0;
};

풀이

factorial이라는 재귀함수를 통해 n!의 값을 구하고 이후 문자열로 변환한 뒤 정규표현식을 통해 뒤쪽에 위치한 연속된 개수의 0을 세어 반환하도록 코드를 작성하였습니다.

제한사항을 보면 n이 최대 10^4까지 될 수 있기 때문에 Number타입이 표현할 수 있는 숫자를 넘어설 수 있어
이를 위해 연산시 BigInt타입으로 변환해 연산이 이루어질 수 있도록 처리했습니다.

리팩토링

위에서 작성한 코드를 제출한 후 3779ms라는 실행 속도를 확인했고 다른 사람들의 답안에 비해 성능이 확연히 떨어지는것을 확인하였습니다.

또한, 문제 지문의 하단에서 시간복잡도 O(log n)으로 풀어보면 좋다고 하여 팩토리얼 값에 규칙성이 있을 거 같아 1! ~ 200!까지의 출력값들을 확인해보았습니다.

사진에서 zeros는 팩토리얼값의 뒤쪽의 연속된 0의 개수를 나타내는데 사진에서 보이듯이 일정한 규칙성을 갖고 있는것을 확인했습니다.

5단위로 0의 개수가 1씩 올라가는데 특이한 점이 25, 50, 75, 100에서는 1이 추가적으로 더 올라가 해당 숫자에서는 2씩 상승되는걸 확인할 수 있습니다.

즉, 팩토리얼값의 뒤쪽에 위치한 연속된 0의 개수는 i의 값을 5로 나눴을 때의 몫의 개수가 되며 해당 몫이 5로 나눠질 수 있다면 그만큼 0이 더 늘어난다는 규칙성을 확인할 수 있었습니다.

그래서, 위와 같은 규칙성을 바탕으로 아래 코드로 리팩토링을 진행하였고 58ms라는 만족스러운 성능을 확인할 수 있었습니다.

const trailingZeroes = function(n, zeros = 0) {
    if (n < 5) return zeros;

    const quotient = Math.floor(n / 5);
    zeros += quotient;

    return trailingZeroes(quotient, zeros);
};

0개의 댓글