https://school.programmers.co.kr/learn/courses/30/lessons/12923
해당 문제는 숫자 블록이 배치되는 규칙성을 찾으면 쉽게 풀 수 있는 문제이다.
숫자 n이 적힌 블록들이 n*2, n*3, n*4, ... 위치에 배치된다. (배치 위치)
또한 숫자 n은 1 부터 시작하여 10,000,000 (천만)까지 이며, (증가 순서 ,크기 제한)
뒤에 배치되는 블록이 먼저 배치된 블록 대신 배치되게 된다. (갱신)
이러한 규칙으로 블록을 배치하게 되면 어떠한 위치 a에 배치되는 숫자는
"어떠한 위치 a 의 약수 중 자신을 제외한 가장 큰 수" 이다.
예를 들어 10번 째 위치를 생각해보자.
10번 째 위치에 배치될 수 있는 숫자 블록은 1, 2, 5 이다.
1을 10번 째 배치 1*10 위치 / 2를 5번 째 배치 2*5 위치 / 5를 2번 째 배치 5*2 위치
또한 n은 1부터 시작되어 이후 배치되는 블록으로 갱신되므로 10번째 위치에는 최종적으로 5가 배치된다.
이 때 위치는 최대 1,000,000,000 (10억) 이지만 숫자는 최대 10,000,000 (천만) 이므로
다시 정리하면 "어떠한 위치 a의 약수 중 자신을 제외하고, 10,000,000 이하인 가장 큰 수 이다."
이것을 코드로 표현하면 다음과 같다.
class Solution {
public int[] solution(long begin, long end) {
int[] answer = new int[(int) (end - begin) + 1];
for (int i = 0; i < answer.length; i++) {
long num = begin + i;
//약수 구하기
int max_divisor = 1;
for (long div = 2; div <= Math.sqrt(num); div++) {
if (num % div == 0) {
//최대 10억의 제곱근이므로 약 3만으로, 천만 이하인지 검사X
int divisor1 = (int) div;
//최대 10억 / 2, 5억이므로 천만이하인지 검사 필요함
int divisor2 = (int) (num / div);
//가장 큰 약수 찾기
max_divisor = Math.max(max_divisor, divisor1);
if ( divisor2 <= 10000000)
max_divisor = Math.max(max_divisor, divisor2);
}
}
answer[i] = max_divisor;
}
if (begin == 1)
answer[0] = 0;
return answer;
}
}
<코드 1 / 가독성 좋음, 성능 낮음>
class Solution {
public int[] solution(long begin, long end) {
int[] answer = new int[(int) (end - begin) + 1];
for (int i = 0; i < answer.length ; i++) {
long num = begin + i;
for (long div = 2; div <= Math.sqrt(num); div++) {
if (num % div == 0) {
if (num / div > 10000000){
answer[i] = (int) div;
continue;
} else{
answer[i] = (int) (num / div);
}
break;
}
}
if (answer[i] == 0) //소수인 경우
answer[i] = 1; //약수가 1과 자기자신 밖에 없다.
}
if (begin == 1)
answer[0] = 0;
return answer;
}
}
<코드 2 / 가독성 낮음, 성능 좋음>
코드 1의 경우 가독성 측면에서는 좋으나
모든 약수를 찾고 그 중에서 가장 큰 약수를 계산하기 때문에 성능은 비교적 떨어진다.
코드 2의 경우 가독성은 안좋으나
가장 큰 약수가 나오면 반복문이 정지하여 성능이 좋다.
약수를 계산하는 부분을 집중해서 보자.
어떠한 수를 나누는 수(div)가 약수라면 그 수로 나누었을 때 몫(num/div) 또한 약수이다.
즉 가장 큰 약수는 가장 처음 나온 (num / div) 값 이다.
하지만 가장 처음 나온 (num / div) 값이 10,000,000 을 넘는다면 그 수는 불가능하다.
그러므로 우선 div 값을 저장하고 다른 약수들이 있는지 계산한다.
만약 없다면 저장된 div 값이 가장 큰 약수이다.
'알고리즘 > 프로그래머스' 카테고리의 다른 글
프로그래머스 Java Lv1 가장 많이 받은 선물 (0) | 2024.03.03 |
---|---|
프로그래머스 Java Lv3 야근 지수 (0) | 2023.10.13 |
프로그래머스 Java Lv2 의상 (1) | 2023.10.07 |
프로그래머스 Java Lv2 두 원 사이의 정수 쌍 (0) | 2023.09.18 |
프로그래머스 Java Lv2 구명 보트 (0) | 2023.09.17 |