이 문제는 사실 시간도 오래 걸리고 어렵게 느껴졌던 문제다,,
단계별로 풀어보기를 순서대로 푸는 중이었는데 갑자기 난이도가 상승한 느낌,,•͈_•͈
풀이 1은 내가 구현한 방법이고, 풀이 2는 많은 분들이 boolean 배열을 이용해서 구현한 것을 보고 참고하여 풀어본 것이다.
알고리즘
우선, 문제를 풀기 전에 셀프 넘버 함수 d(n)을 구현하는 방법에 대해서 알아두면 좋을 것 같다.
예를 들어, numSum(123) = 123+1+2+3 = 129 가 저장되게끔 하려면 다음과 같이 구현할 수 있다.
1. n이라는 수를 받으면 이를 나중에 리턴 시킬 변수 self에 저장한다.
static int d(int n) {
int self = n;
}
2. 각 자릿수의 합을 구하기 위해 n을 10으로 나눈 나머지를 self 변수에 더해 저장해주고, 이후 n은 10으로 나눈 몫을 저장해 한 자릿수를 줄여준다. n을 10으로 나눈 몫이 0이 될 때까지 반복하면 모든 자릿수를 더할 수 있다.
예를 들어, n = 123이라고 한다면,
첫 번째 반복문에서 self에는 123 + (123%10) = 123+3 = 126 이 저장되고,
n에는 (123/10) = 12가 저장된다.
두 번째 반복문에서 self에는 126 + (12%1) = 126+2 = 128 이 저장되고,
n에는 (12/10) = 1이 저장된다.
세 번째 반복문에서 self에는 128 + (1%10) = 128+1 = 129 가 저장되고,
n에는 1/10 = 0 이 저장된다.
while(n>0)의 조건을 만족하지 않으므로 self값을 리턴하고 while문을 빠져나온다.
static int d(int n) {
int self = n;
while(n>0) {
self += n%10; //10으로 나눈 나머지 저장
n = n/10; //자릿수 줄이기
}
return self;
}
문제
4673번: 셀프 넘버
셀프 넘버는 1949년 인도 수학자 D.R. Kaprekar가 이름 붙였다. 양의 정수 n에 대해서 d(n)을 n과 n의 각 자리수를 더하는 함수라고 정의하자. 예를 들어, d(75) = 75+7+5 = 87이다. 양의 정수 n이 주어졌을 때,
www.acmicpc.net
풀이 1
함수 d()를 만들고, main에서는 int 배열을 생성하여 d() 함수의 리턴 값을 index로 지정하여 생성자가 존재하는 경우에 해당 index를 count 하는 방법을 이용하였다.
이때, index는 0~9999의 값이지만, i는 1~10000까지이므로 배열에 넣을 때 한 칸씩 당겨서 들어간다는 점을 유의해야 한다.
public class Main{
public static void main(String[] args){
int[] arr = new int[10000]; //생성자 수를 저장할 배열 선언
for(int i=1; i<=10000; i++) {
//i를 10000까지 넣으면, d(i)는 10000을 초과하는 경우가 발생하므로 d(i)<=10000 까지만 실행
if(d(i)<=10000) {
arr[d(i)-1]++; //생성자가 존재하는 경우 count (i는 1~10000이지만, 배열의 index는 0~9999라는 점을 고려하여 1을 꼭 빼줘야함!!)
}
}
for(int i=0; i<10000; i++) {
//셀프 넘버=생성자가 존재하지 않는 경우(->해당 index가 count되지 않아 초기값 0이 저장된 경우)
if(arr[i]==0){
System.out.println(i+1); //arr[i]에는 i+1의 생성자 수가 저장되어 있으므로 i+1 출력
}
}
}
static int d(int n){
int self = n;
while(n>0) { //n이 0이 되면 종료
self += n%10; //10으로 나눈 나머지 저장
n= n/10; //자릿수 하나씩 줄이기
}
return self;
}
}
풀이 2
int 배열 대신 boolean 배열을 선언하여 풀어보았다. 그리고 StringBuilder를 이용하여 속도를 높였다.
StringBuilder는 문자열을 이어주는 역할을 하며 객체를 생성하지 않아서 속도가 빠르다.
public class Main {
public static void main(String[] args) {
boolean[] arr = new boolean[10000];
for(int i=1; i<=10000; i++) {
if(d(i)<=10000) {
arr[d(i)-1] = true;
}
}
StringBuilder sb = new StringBuilder();
for(int i=0; i<10000; i++){
if(arr[i]!=true) { //false인 인덱스만 출력
sb.append(i+1).append('\n');
}
}
System.out.println(sb);
}
public static int d(int n) {
int self = n;
while(n>0) {
self += n%10;
n = n/10;
}
return self;
}
}
'문제 풀이 > BAEKJOON' 카테고리의 다른 글
[백준/JAVA] 11654번. 아스키 코드 (0) | 2021.08.05 |
---|---|
[백준/JAVA] 1065번. 한수 (0) | 2021.08.04 |
[백준/JAVA] 1546번. 평균 (0) | 2021.07.31 |
[백준/JAVA] 2577번. 숫자의 개수 (0) | 2021.07.28 |
[백준/JAVA] 15552번. 빠른 A + B (0) | 2021.07.24 |
댓글