nums
숫자들이 들어있는 배열 | [1,2,3,4] | 숫자의 개수는 3개 이상 50개 이하, 최대 각 원소는 1 이상 1,000 이하의 자연수
=> nums에 있는 숫자들 중 서로 다른 3개를 골라 더했을 때 소수가 되는 경우의 개수를 return
에라토스테네스의 체를 이용해 소수를 미리 구하고, 조합을 통해 3개를 뽑은 뒤 소수인지 판별하여 cnt 1 증가
class Solution {
public int solution(int[] nums) {
boolean[] isNotPrime = new boolean[3000];
for(int i=2; i<3000; i++){
for(int j=2; i*j<3000; j++){
isNotPrime[i*j] = true;
}
}
return nCr(-1,0,0,nums,isNotPrime);
}
public int nCr(int start, int cnt, int sum, int[] nums, boolean[] isNotPrime){
if(cnt == 3){
if(!isNotPrime[sum]){
return 1;
}
return 0;
}
int cur_ans = 0;
for(int i=start+1; i<nums.length; i++){
cur_ans += nCr(i, cnt+1, sum+nums[i], nums, isNotPrime);
}
return cur_ans;
}
}
=> 에라토스테네스의 체를 최적화 해야겠음
import java.util.*;
class Solution {
public int solution(int[] nums) {
boolean[] isPrime = new boolean[3000];
Arrays.fill(isPrime, true);
for(int i=2; i<=(int) Math.sqrt(3000); i++){
if(isPrime[i]){
for(int j=i*i; j<3000; j+=i){
isPrime[j] = false;
}
}
}
return nCr(-1,0,0,nums,isPrime);
}
public int nCr(int start, int cnt, int sum, int[] nums, boolean[] isPrime){
if(cnt == 3){
if(isPrime[sum]){
return 1;
}
return 0;
}
int cur_ans = 0;
for(int i=start+1; i<nums.length; i++){
cur_ans += nCr(i, cnt+1, sum+nums[i], nums, isPrime);
}
return cur_ans;
}
}
=> Arrays.fill()로 3000 사이즈의 배열에 초기값을 설정하는 과정을 추가해야 했음
class Solution {
public int solution(int[] nums) {
boolean[] isNotPrime = new boolean[3000];
for(int i=2; i<=(int) Math.sqrt(3000); i++){
if(!isNotPrime[i]){
for(int j=i*i; j<3000; j+=i){
isNotPrime[j] = true;
}
}
}
return nCr(-1,0,0,nums,isNotPrime);
}
public int nCr(int start, int cnt, int sum, int[] nums, boolean[] isNotPrime){
if(cnt == 3){
if(!isNotPrime[sum]){
return 1;
}
return 0;
}
int cur_ans = 0;
for(int i=start+1; i<nums.length; i++){
cur_ans += nCr(i, cnt+1, sum+nums[i], nums, isNotPrime);
}
return cur_ans;
}
}
=> 미미하지만, 전보다 빠르게 실행 가능했음
Tip : 에라토스테네스의 체를 구현할 때, 루트 범위까지만 봐도 소수를 전부 구분할 수 있다.