Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 백준11399
- 백준12891
- 백준2023
- 백준10998
- 백준2751
- 백준1260
- 백준2018
- 백준11003
- 백준1517
- 버블소트
- 백준1253
- 백준1874
- 백준1427
- Java
- 백준2750
- 구간합
- 백준_11659
- 백준11720
- 백준11286
- 정렬알고리즘
- 백준1377
- 자바
- 백준
- 백준1940
- 백준13023
- stack
- 백준11724
- 백준17298
- 백준_구간합구하기
- 백준1546
Archives
- Today
- Total
HOONDOC
[백준]2023 신기한 소수 - 자바/Java 본문
2023번: 신기한 소수
🌱풀이
알고리즘
- 백트래킹이 핵심이다. 백트래킹의 조건은 아래와 같다.
- DFS(a, b) 중 a는 자릿수의 숫자, b는 자리수다. DFS(2,1)은 일의 자리가 2일때다.
- 한 자리 수에서 존재하는 소수는 2,3,5,7 뿐이다. 첫째 자리 수가 2,3,5,7일 때 자리수를 높여가며 DFS 탐색을 코드를 작성하면 된다.
- DFS 메소드의 첫 줄에는 종료 조건을 작성한다. 목표 자리수에 도달했을 때의 숫자가 소수이면 모든 조건을 만족했으므로 출력 한다.
- 아래 1부터 9까의 반복문은 모듈러 연산을 통해 소수를 판단한다. 소수가 아니면 넘기고, 소수로 판명되면 자릿수를 높여 DFS 메소드를 호출해 재귀 함수를 만든다.
- 이 때 소수 판명은 메소드를 따로 작성해주는게 깔끔하다.
메모리 : 11552KB, 시간 : 820ms
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N;
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//한 자리 수에서 소수는 2,3,5,7 뿐이다. 자리수별 소수 조건을 걸어줘서 백트래킹 하기
N = Integer.parseInt(br.readLine());
//한 자리에서 소수인 것부터 탐색
DFS(2,1);
DFS(3,1);
DFS(5,1);
DFS(7,1);
}
static void DFS(int number, int J) {
//해당 자리수에 도달하면
if(J == N) {
if(isPrime(number)) System.out.println(number);
return;
}
for(int i = 1; i<10; i++) {
if( i % 2 == 0) continue; //소수가 아님
if(isPrime(number*10+i)) DFS(number * 10 +i, J+1);
}
}
static boolean isPrime(int num) {
for(int i = 2; i<=num/2; i++) {
if(num%i == 0) return false;
}
return true;
}
}
🪴코드 리뷰
🌿메모리 : 11568KB, 시간 : 80ms
백트래킹 조건을 좀 더 섬세하게 설정하면 코드의 성능을 높일 수 있다. 아래 코드는 소수 판별 메소드에서 반복문의 범위를 변경했다. 기존 코드에서는 i <= num/2 였지만 여기선 i*i <= num 이다. 소수를 판별하는 알고리즘에는 여러가지가 있을 수 있는데, Conclusion의 블로그를 참고해보자.
최초 코드의 조건은 무척 단순한데, 자기 자신의 절반보다 큰 수 중에서 자기 자신을 나눌 때 0이 되는 숫자는 존재하지 않기 때문이다. 여기서 좀 더 응용하면, 해당 숫자의 제곱근까지만 확인하는 방식이다. 도저히 이해가 안되면 외우는 것도 방법이다.
💡 풀이자 : 본인
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N;
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//한 자리 수에서 소수는 2,3,5,7 뿐이다. 자리수별 소수 조건을 걸어줘서 백트래킹 하기
N = Integer.parseInt(br.readLine());
//한 자리에서 소수인 것부터 탐색
DFS(2,1);
DFS(3,1);
DFS(5,1);
DFS(7,1);
}
static void DFS(int number, int J) {
//해당 자리수에 도달하면
if(J == N) {
if(isPrime(number)) System.out.println(number);
return;
}
for(int i = 1; i<10; i++) {
if( i % 2 == 0) continue; //소수가 아님
if(isPrime(number*10+i)) DFS(number * 10 +i, J+1);
}
}
static boolean isPrime(int num) {
for(int i = 2; i*i<=num; i++) {
if(num%i == 0) return false;
}
return true;
}
}
🌿메모리 : 11500KB, 시간 : 88ms
백트래킹 조건을 좀 더 자세하게 넣어봤는데 시간이 증가했다. 백준 서버 이슈일수도 있는데 성능 차이는 크게 안나는 것 같다. 제곱근까지만 검사하는걸로 엥간하면 커버가 되는 것 같다.
💡 풀이자 : 본인
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N;
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//한 자리 수에서 소수는 2,3,5,7 뿐이다. 자리수별 소수 조건을 걸어줘서 백트래킹 하기
N = Integer.parseInt(br.readLine());
//한 자리에서 소수인 것부터 탐색
DFS(2,1);
DFS(3,1);
DFS(5,1);
DFS(7,1);
}
static void DFS(int number, int J) {
//해당 자리수에 도달하면
if(J == N) {
if(isPrime(number)) System.out.println(number);
return;
}
for(int i = 1; i<10; i++) {
if( i % 2 == 0) continue; //소수가 아님
if( J > 1 && number % 5 == 0) continue;
if( J > 1 && sumOfJarisu(number) % 3 == 0) continue;
if(isPrime(number*10+i)) DFS(number * 10 +i, J+1);
}
}
static boolean isPrime(int num) {
for(int i = 2; i*i<=num; i++) {
if(num%i == 0) return false;
}
return true;
}
static int sumOfJarisu(int num) {
String stringNumber = String.valueOf(num);
int sum = 0;
for(int i = 0; i<stringNumber.length(); i++) {
sum += stringNumber.charAt(i) -'0';
}
return sum;
}
}
Conclusion
- 소수 판별 알고리즘 익혀두기
- 첫째 자리수를 기준으로 자릿수를 높여가며 판단하는게 깊이 우선 탐색과 닮아있지 않은가? 이건 감각의 영역인 것 같다. 이런 발상이 안되면 문제를 많이 풀어서 감각을 만들어주는 수 밖에는 없다.
- 난 문제를 많이 풀어봐야한다.
'문제 풀이 > BAEKJOON' 카테고리의 다른 글
[백준]1260 DFS와 BFS - 자바/Java (0) | 2023.01.08 |
---|---|
[백준]2750 수 정렬하기 2 - 자바/Java (0) | 2023.01.06 |
[백준]11724 연결 요소의 개수 - 자바/Java (0) | 2023.01.06 |
[백준]2750 수 정렬하기 2 - 자바/Java (0) | 2023.01.05 |
[백준]1517 버블 소트 - 자바/Java (0) | 2023.01.05 |