본문 바로가기
코딩테스트/백준

[백준 4673] 셀프 넘버 - Java (+)

by naahy 2022. 10. 18.

🔗https://www.acmicpc.net/problem/4673

 

4673번: 셀프 넘버

셀프 넘버는 1949년 인도 수학자 D.R. Kaprekar가 이름 붙였다. 양의 정수 n에 대해서 d(n)을 n과 n의 각 자리수를 더하는 함수라고 정의하자. 예를 들어, d(75) = 75+7+5 = 87이다. 양의 정수 n이 주어졌을 때,

www.acmicpc.net

 

 



처음엔 문제를 이해하는 것도 어려웠다.
셀프 넘버가 뭔진 대충 알겠는데, 이 수가 셀프 넘버인지 아닌지 대체 어떻게 알지?
식을 내가 새롭게 세워야 하나? 하지만 테스트 땐 검색을 못할텐데... 별의 별 생각을 다했다.


다시 생각해보니 그 수가 셀프넘버인지 아닌지 아는 건 필요 없었다.
필요했으면 그 방법을 문제에서 먼저 제시했겠지...
문제에서 주어진 정보 외의 것을 사용하려고 하는 버릇을 버려야겠다는 생각이 들었다.

 

 

✨ 참고

https://junghn.tistory.com/m/entry/%EC%9E%90%EB%B0%94-int%EB%A5%BC-%EC%9E%90%EB%A6%BF%EC%88%98%EB%B3%84-int-%EB%B0%B0%EC%97%B4%EB%A1%9C-%EB%B6%84%ED%95%A0

 

[JAVA] 자바에서 int형의 숫자를 각각의 자릿수 구하는 방법

알고리즘 문제를 풀 때 int형 숫자에서 각각의 자릿수를 구하는 방법이 필요할 때가 있습니다. 오늘은 int형 숫자에서 각각의 자릿수를 구하는 3가지 방법에 대해 정리해 보겠습니다. 1. 나눗셈 연

junghn.tistory.com

 

https://velog.io/@yu-jin-song/BOJ-4673-%EC%85%80%ED%94%84-%EB%84%98%EB%B2%84

 

[BOJ] 4673 셀프 넘버 (JAVA)

(6단계) 함수 2 - 함수 d를 정의하여 문제 해결하기

velog.io

 


 

더보기

풀이1

  • 셀프넘버가 아닌 숫자들을 담을 HashSet 선언
  • 함수 d 작성
  • 1부터 10000까지의 정수 n에 대한 d(n) 값을 HashSet에 저장
  • 다시 for문을 통해 1부터 10000까지 돌며 각 숫자가 HashSet에 들어있는지 확인
    • 들어있지 않다면 해당 숫자는 셀프넘버

 

코드

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashSet;
//import java.util.stream.Stream;

public class SelfNumber4673 {

	public static void main(String[] args) throws IOException {
		SelfNumber4673 sn = new SelfNumber4673();	// 클래스 내 메소드 호출 위함
		
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		HashSet<Integer> notSelfNumber = new HashSet<Integer>();
		
		for (int n=1; n<=10000; n++) {
			notSelfNumber.add(sn.d(n));
		}
		
		for (int n=1; n<=10000; n++) {
			if (!notSelfNumber.contains(n))
				bw.write(n + "\n");
		}
		bw.close();
	}
	
	int d(int n) {
		int newNum = n;
		
		// 1. 문자열로 변환해서 구하기
		String strN = Integer.toString(n);
		
		for (int i=0; i<strN.length(); i++) {
			newNum += strN.charAt(i) - '0';
		}
		
		// 2. Stream 이용해 구하기 - 시간 더 오래 걸림
//		for (int i : Stream.of(String.valueOf(n).split("")).mapToInt(Integer::parseInt).toArray()) {
//			newNum += i;
//		}
		
		return newNum;
	}

}

 


 

풀이2

정수가 들어가는 HashSet 대신 boolean 값이 들어가는 배열을 이용하는 방법도 있다.

수행 시간을 확인해보니 훨씬 시간이 덜 걸리는 것을 알 수 있었다.

방법은 동일하다.

  • 배열의 크기는 넉넉잡아 100001로 설정
  • 배열의 d(n) 위치 값을 true로 설정
  • false 값을 가지는 인덱스 출력

 

코드

//		HashSet<Integer> notSelfNumber = new HashSet<Integer>();
		boolean[] notSelfNumber = new boolean[100001];
		
		for (int n=1; n<=10000; n++) {
//			notSelfNumber.add(sn.d(n));
			notSelfNumber[sn.d(n)] = true;
		}
		
		for (int n=1; n<=10000; n++) {
//			if (!notSelfNumber.contains(n))
			if (!notSelfNumber[n])
				bw.write(n + "\n");
		}
		bw.close();

주석 처리한 부분은 기존 코드 내용이다.

밑줄의 내용으로 바꾸면 된다.

 

풀이 3 (+ 23.08.09)

셀프 넘버는 10,000보다 작으므로 d(n) 함수 내에서 다른 함수 호출 없이 각 자리별 수를 바로 구했다.

  • 크기 10,000인 boolean 배열 생성
  • 배열 크기만큼 for문 돌면서 d(n) 함수 실행
    • 결과가 10,000보다 크면 continue
    • 작으면 배열의 해당 인덱스 값을 true로 설정
  • 배열 내 요소가 false면 해당 요소의 인덱스 값 출력

 

코드

public class Main {
	
	static int d(int n) {
		int n4 = n / 1000;
		int n3 = n % 1000 / 100;
		int n2 = n % 100 / 10;
		int n1 = n % 10;
		
		return n + n1 + n2 + n3 + n4;
	}

	public static void main(String[] args) {
		boolean numArr[] = new boolean[10000];
		
		for (int i=1; i<10000; i++) {
			int num = d(i);
			if (num >= 10000)	continue;
			numArr[num] = true;
		}
		
		for (int i=1; i<10000; i++) {
			if (numArr[i] == false)
				System.out.println(i);
		}
	}

}

댓글