프로그래머스 Level 1
🔒 소수 찾기
1부터 입력받은 숫자 n 사이에 있는 소수의 개수를 반환하는 함수, solution을 만들어 보세요.
소수는 1과 자기 자신으로만 나누어지는 수를 의미합니다.
(1은 소수가 아닙니다.)
n | result |
---|---|
10 | 4 |
5 | 3 |
입출력 예 #1
1부터 10 사이의 소수는 [2,3,5,7] 4개가 존재하므로 4를 반환
입출력 예 #2
1부터 5 사이의 소수는 [2,3,5] 3개가 존재하므로 3를 반환
class Solution {
public int solution(int n) {
int answer = 0;
for(int i=2; i<n; i++) {
boolean yn = false;
for(int j=2; j<i/2; i++) {
if(i % j == 0) yn = true;
}
if(!yn) answer++;
}
return answer;
}
}
아 감자는 이중 for문 안좋아하긴 하는데 생각나는 방법이 이거뿐이였다.
1은 소수가 아니므로 2부터 시작하고 소수가 아니면 true이게 해놓아서 소수 여부를 체크한 후 answer에 1을 더했다.
그래도 나름 코드는 잘 적지 않았나 싶었는데
...에?
처음부터 다시 생각해보자... 일단 초기화...
그리고 질문하기에 방문...!!
음... 너무 복잡한걸? 🤕
일단 생각나는 대로 작성해보자!!
import java.util.ArrayList;
class Solution {
public int solution(int n) {
ArrayList<Integer> answ = new ArrayList<Integer>();
answ.add(2);
for(int i=3; i<=n; i+=2) {
boolean yn = false;
for(int j : answ) {
if(i % j == 0) yn = true;
}
if(!yn) answ.add(i);
}
int answer = answ.size();
return answer;
}
}
질문하기에서 얻은 조언 중 1번, 3번만 적용했을 때의 코드이다.
n
은 무조건 2 이상이므로 소수를 담아두는 리스트 answ
에 미리 담아두고 3부터 2씩 증가하여(짝수는 약수 2를 가지므로 홀수만 비교) 소수 리스트 answ
와 비교한다.
하지만 테스트 10에서 탈락...
제곱근을 사용하는 수 밖에 없는 것인가ㅠㅠ
import java.util.ArrayList;
class Solution {
public int solution(int n) {
int answer = 1; // 소수 2
ArrayList<Integer> answ = new ArrayList<Integer>();
for(int i=3; i<=n; i+=2) {
boolean yn = false;
for(int j : answ) {
if(i % j == 0) yn = true;
}
if(!yn) {
if(i <= Math.sqrt(n)) answ.add(i);
else answer++;
}
}
answer += answ.size();
return answer;
}
}
이번엔 n
의 제곱근보다 작은 소수일 경우 리스트 answ
에 담고 n
의 제곱근보다 크면 그냥 answer
의 수를 증가했다.
이렇게 한다면 n
의 제곱근보다 큰 소수들은 굳이 비교하지 않으므로 비교수가 줄어들 것이다. 그렇다면 효율성 테스트도 통과하지 않을까?! 😀
응 아니야
질문하기에서 본 조언은 다 충족한 거 같은데 왜 통과를 못하는 걸까...😵
다시 질문하기에 방문!!
에라토스테네스의 체...??
제곱근보다 작은 소수들의 배수를 지우고 남는 수는 모두 소수이다!!
그림의 경우, 11^2>120이므로 11보다 작은 수의 배수들만 지워도 충분하다. 즉, 120보다 작거나 같은 수 가운데 2, 3, 5, 7의 배수를 지우고 남는 수는 모두 소수이다.
📑 출처
오오!! 그러니깐 이거 다 갈아엎고 공부해야한다는 소리지?! 🥴
위키피디아 가면 아래에 친히 언어별 코드까지 다 있다
class Solution {
public int solution(int n) {
int answer = 0;
int[] number = new int[n+1];
for(int i = 0; i < n+1; i++) number[i] = i;
for(int i = 2; i < n+1; i++) {
if(number[i] != 0) {
for(int j=i+i; j<n+1; j+=i) {
number[j] = 0;
}
}
}
for(int i = 2; i < n+1; i++) {
if(number[i] != 0) answer++;
}
return answer;
}
}
n+1
만큼의 크기를 가진 배열 number
을 생성해준 후 각자 배열의 위치와 동일한 숫자를 입력해주었다. (크기를 n으로 하여 m번째 위치에 m+1이 들어가게 할 수 있으나 헷갈릴까봐 n+1로 했다.)
그다음 제한 조건의 최소값인 2부터 시작하여 n이 될 때까지 각 수의 배수의 위치에는 0으로 재정의한다.
마지막으로 다시 한번 2부터 반복문을 돌려 0이 아닐 경우에는 answer
의 수를 증가했다.
과연 이번에 결과는...?!
이 문제를 푸는 데 약 이틀이 걸렸다.
최대한 감자만의 방법으로 하고 싶었는데 결국 수학을 공부해야 풀 수 있는 문제였다.
세상엔 다양한 수학 이론이 있구나 싶으면서도 코딩과 수학은 뗄레야 뗄 수 없는 관계인 게 감자를 아찔하게 만든다...
수학 공부... 다시 해봐야하나? 😢