Level 0. 소인수분해
소인수분해는 다음과 같은 과정을 통해 수행할 수 있다.
n = 120을 예로 들 때
- i는 2부터 시작한다.
- n이 1이 아닌 동안 반복한다.
- 1씩 증가시키며 나누어 떨어지는 수 i를 찾는다.
- i를 소인수 리스트에 추가한다.
- n이 더 이상 나누어 떨어지지 않을 때까지 i로 나눈다.
- 2로 돌아가 과정을 반복한다.
아래는 재귀를 이용하여 부문제로 나누어 해결한 풀이이다.
예들 들면
- solution(120)은 2와 solution(60)의 결과를 합친 것이다.
- solution(60)은 2와 solution(30)의 결과를 합친 것이다.
- solution(30)은 2와 solution(15)의 결과를 합친 것이다.
- solution(15)는 3과 solution(5)의 결과를 합친 것이다.
- solution(15)는 3와 solution(5)의 결과를 합친 것이다.
- solution(5)는 5이다.
중복 원소 제거와 정렬을 위해 set을 사용하였으나 마지막 풀이에서 중복 원소를 제거할 필요 없이 좀 더 최적화하는 방법이 나와있다.
참고했던 자료에서는 i를 추가할 때도 solution(i)와 같이 소인수분해하여 추가했는데 그럴 필요는 없다.
- i가 작은 수부터 시작하기 때문에 나누어 떨어지는 수 i는 항상 소수이다.
- i = 2j라고 할 때, i가 나누어 떨어지는데 j를 확인하지 않았다는 건 말이 안 되기 때문이다.
#include <iostream>
#include <vector>
#include <set>
using namespace std;
vector<int> solution(int n)
{
for (int i = 2; i < n; ++i)
{
if (n % i == 0)
{
set<int> st = {i};
vector<int> v = solution(n / i);
st.insert(v.begin(), v.end());
return vector<int>(st.begin(), st.end());
}
}
return vector<int>({n});
}
아래는 반복문을 통해 해결한 풀이이다.
- i < n이 아니라 1 < n이 종료 조건임에 주의해야 한다.
i가 나누어 떨어지는 수인 경우 i를 증가시키지 않고 계속 n을 나눈다.
마지막에 정렬 후 중복 원소를 제거하여 반환한다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> solution(int n)
{
vector<int> answer;
for (int i = 2; 1 < n;)
{
if (n % i == 0)
{
n /= i;
answer.emplace_back(i);
}
else
{
++i;
}
}
sort(answer.begin(), answer.end());
answer.erase(unique(answer.begin(), answer.end()), answer.end());
return answer;
}
정렬과 중복 제거를 하지 않아도 되는 풀이이다.
나누어 떨어지는 수를 찾은 경우 그냥 그때 한 번에 다 나눠버리는 것이다.
i가 작은 수부터 시작하므로 정렬할 필요도 없고 1번만 삽입하므로 중복 제거도 불필요하다.
#include <iostream>
#include <vector>
using namespace std;
vector<int> solution(int n)
{
vector<int> answer;
for (int i = 2; 1 < n; ++i)
{
if (n % i == 0)
{
answer.emplace_back(i);
do
n /= i;
while (n % i == 0);
}
}
return answer;
}
'자료구조 & 알고리즘 > 프로그래머스' 카테고리의 다른 글
Level 1. 문자열 내 p와 y의 개수 (0) | 2023.02.09 |
---|---|
Level 0. 유한소수 판별하기 (0) | 2023.02.08 |
Level 0. 구슬을 나누는 경우의 수 (0) | 2023.02.06 |
Level 0. 다항식 더하기 (0) | 2023.02.05 |
Level 0. 분수의 덧셈 (0) | 2023.02.04 |