[프로그래머스] 소수찾기 (Java)
zl존석동
·2022. 2. 3. 21:16
프로그래머스 level2 - 소수 찾기 풀이
코딩테스트 연습 - 소수 찾기
한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다. 각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이
programmers.co.kr
문제 간단 요약
- 문자열로 0~9의 숫자들이 주어진다.
- 해당 숫자 하나 하나로 만들 수 있는 모든 조합의 숫자들 중 소수의 개수를 구하라
나의 풀이
1. 숫자를 조합해 만든 여러 수들 중 같은 수가 있다면 한번만 카운트해야함.
=> Set 사용
2. 숫자 조합을 만들 때 자기 자신이 들어가면 안된다.
예를 들어 입력이 "171" 이면
숫자 하나에 다른걸 붙여 두자리 수를 만들면
| 11 17 71 |
두 자리수에 한 자리수들을 모두 앞뒤로 붙여 세자리 수를 만든다고 생각했을 때
| 117 711 171 111??? |
자기 자신이 포함되어있었던 건지 아닌건지 체크할 방법이 떠오르지가 않았다.
그래서 숫자 문자열을 입력받았을 때 0~9 까지 모두 몇개가 있나 세어주는 배열을 만들고 체크하는 메소드를 활용했다.
// 입력받을 숫자 1의자리수 총 갯수에 대한 배열
int[] countArr = new int[10];
/**
* @param n : 넣을 숫자 문자열
* @param checkArr : 입력받은 숫자 문자열들 0~9까지의 count 배열
* @return true: set에 넣어도 되는 숫자다.
*/
private static boolean checkNumLimit(String n, int[] checkArr) {
for (int i = 0; i < n.length(); i++) {
char c = n.charAt(i);
if (n.chars().filter(v -> c == v).count() > checkArr[c - 48]) {
return false;
}
}
return true;
}
Set 에 모든 조합 가능한 수를 넣으면서도
해당 숫자개수 체크 메소드를 활용해 자기 자신이 포함되었는지 아닌지 여부를 증명해줄 수 있게 되었다.
Java 풀이 코드
import java.util.Set;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;
public class Solution {
// 입력받을 숫자 1의자리수 총 갯수에 대한 배열
private static int[] countArr = new int[10];
private static Set<String> set = new CopyOnWriteArraySet<>();
public static int solution(String numbers) {
// 자릿수별 숫자개수 할당
numbers.chars().forEach(v -> countArr[v - 48]++);
// [입력받은 숫자] 루프
for (int i = 0; i < numbers.length(); i++) {
// 루프를 돌며 각각 1자리를 Set에 더해줌
set.add(numbers.charAt(i) + "");
Iterator<String> it = set.itertor();
// Set 의 모든 값들을 돌며
while (it.hasNext()) {
// Set에 현재 있는 값들에 [입력받은 숫자] 각각 1자리들을 붙여줌
pushToSet(it.next(), numbers);
}
}
// String Set => Integer Set
Set<Integer> intSet = set.stream().map(Integer::parseInt).collect(Collectors.toSet());
// Integer Set 에서 소수만 찾아서 개수 리턴
return (int) intSet.stream().filter(v -> isPrimeNumber(v)).count();
}
// Set에 숫자를 넣는 메소드
private static void pushToSet(String currentValue, String numbers) {
for (int j = 0; j < numbers.length(); j++) {
if (checkNumLimit(currentValue + numbers.charAt(j), countArr)) {
// 현재 Set에 존재하는 숫자 앞뒤에 숫자한개를 붙임
set.add(currentValue + numbers.charAt(j));
set.add(numbers.charAt(j) + currentValue);
}
}
}
/**
* @param n : 넣을 숫자 문자열
* @param checkArr : 입력받은 숫자 문자열들 0~9까지의 count 배열
* @return true : set에 넣어도 되는 숫자다.
*/
private static boolean checkNumLimit(String n, int[] checkArr) {
for (int i = 0; i < n.length(); i++) {
char c = n.charAt(i);
if (n.chars().filter(v -> c == v).count() > checkArr[c - 48]) {
return false;
}
}
return true;
}
// 소수 찾는 메소드
private static boolean isPrimeNumber(int n) {
if (n <= 1) {
return false;
}
for (int i = 2; i <= (int) Math.sqrt(n); i += 1) {
if (n % i == 0) {
return false;
}
}
return true;
}
public static void main(String[] args) {
System.out.println(solution("011"));
}
}
자기 자신 문제 때문에 모든 조합가능한 수를 찾지 못해서 틀리던가 너무 많이 조합해서 틀리던가 하며 푸느라 애먹었었는데
풀고 다른 사람 풀이를 보니 자기 자신을 제외하고 문자열의 subString 메소드와 재귀를 이용하여 그런 체크 따위 할 필요가 없게 풀었다.
public void permutation(String prefix, String str, HashSet<Integer> set) {
int n = str.length();
if(!prefix.equals("")) set.add(Integer.valueOf(prefix));
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n), set);
}
'알고리즘 & 자료구조 > 프로그래머스' 카테고리의 다른 글
| [프로그래머스] 스킬트리 (java) (0) | 2022.08.24 |
|---|---|
| [프로그래머스] 파일명 정렬 (java) (0) | 2022.08.15 |
| [프로그래머스] 파괴되지 않은 건물(java) (0) | 2022.07.18 |
| [프로그래머스] 다리를 지나는 트럭 (java) (0) | 2022.01.13 |
| [프로그래머스] 기능개발(Java) (0) | 2022.01.13 |