본문 바로가기

알고리즘/리트코드

172번 Factorial Trailing Zeroes 풀이(c++)

반응형

풀이 해설을 요청하신 분이 있어서..

이 문제는 'trailing zero'을 구하는 문제이다.

숫자의 가장 뒤에 연속해서 붙어오는 0의 갯수를 세는 문제라고 말해도 될것같다.

(단 0인경우에는 숫자를 세지 않는다)

 

처음에는 주어진 숫자를 문자열로 바꿔서 맨 뒤에 있는 0의 갯수를 세는걸로 생각했지만,

더 효율적인 방법이 있을거라 판단하고 생각하다보니 한 가지 규칙을 발견하게 되었다.

 

n! = x * 10^r

 맨 뒤에 연속해서 오는 숫자가 r이라고 할 때, 위와 같은 수식으로 문제를 바꿔서 표현할 수 있다. 오히려 '맨 뒤에 있는 0의 갯수'보다 위 식이 훨씬 간결하고 정확하게 문제를 정의하고 있다. 즉, n!을 소인수분해하여 나오는 10의 갯수가 이 문제의 정답이 된다.

 

 10을 소인수분해하면 '2*5'임을 알 수 있는데, 2를 인수로 갖는 숫자는 짝수이고, 5를 인수로 갖는 숫자는 5의 배수임을 알 수 있다. 즉, 인수 2의 갯수가 5의 갯수보다 항상 많기 때문에 5의 갯수만 생각하면 그것이 10의 갯수랑 동일하다.

 

 이때 n=>n! 이므로, n을 5로 나누었을 때의 몫이 1부터 n까지의 수 중에서 '1개 이상의 5를 인수로 갖는 수'임을 알 수 있다. 예를 들어 n이 첫번째 5의 배수인 5보다 작은 경우, n을 5로 나누었을때의 몫은 0이다. 첫번째 5를 갖는 5부터 n/5의 몫은 1이 되고, 10이 되는 순간 n/2의 몫은 2가 된다. 여기서 '1개 이상의 5'라는 단어를 사용하였는데, 한가지 수에 2개 이상의 5를 가지는 경우도 생길 수 있다. 5의 제곱의 경우 한 숫자에 2개의 5를 인수로 가지게 된다.

 

 1~n범위에 n의 제곱수중 지수가 가장큰 수까지 처리하기 위해 재귀함수를 이용해 문제를 해결하였다. n을 5로 나누면 '1개 이상의 5를 인수로 갖는 수'를 알 수 있고, n을 5의 제곱으로 나누면 '2개 이상의 5를 인수로 갖는 수'를 알 수 있다. 이렇게 나누는 5를 계속 제곱시켜 몫이 0이 나올때까지 함수를 반복하고, 함수의 반환값이 0이 나오는 순간 지금까지의 모든 연산을 더해 결과를 제출하였다.

 

 

코드

    int devideFive(int n){
        if(n<=0) return 0;
        return devideFive((int)n/5) + (int)n/5;
    }
    int trailingZeroes(int n) {
        return devideFive(n);
    }

 

 

 

 

Factorial Trailing Zeroes - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

 

 

 

반응형