출처: https://meyouus.tistory.com/64 [정보 공유 - For Me For You For Us]
본문으로 바로가기

 

내가 싫어하는 소수 문제이다. 언제나 봐도 생각이 잘 안나기 때문에 매번 새롭게 머리를 굴려야 된다는 느낌이 있다. 우선 처음에 짠 풀이는 다음과 같다:

def solution(n):
    list_n1 = [x+1 for x in range(n)]
    list_n1.remove(1)
    list_n2 = sorted(list_n1, reverse=True)
    for i in list_n1:
        for j in list_n2:
            if i == j:
                continue
            elif j%i == 0:
                list_n2[list_n2.index(j)] = 0
    
                
    return len(list(set(list_n2)))-1

우선 list_n1을 1 부터 n까지의 리스트로 정의를 하고, 1을 제외시켜준다.

list_n2list_n1의 역순인 리스트로 정의해준다.

ilist_n1의 순서로, jlist_n2의 순서로 정의를 해주고 만약 ji로 나누었을 때 0으로 나온다면, list_n2에서 해당 값을 0으로 설정해준다.

마지막으로 list_n2set으로 통과시키고 이를 리스트로 만들어서 길이를 구하고, 이에 0이 포함되어 있으므로 1을 빼준다.

 

원리상 완벽해보이지만, 하나는 에러가 나고, 시간초과가 나는 테스트 값들이 여럿 있었다. 에러가 나는 값은 n 값이 2일때 인 것을 알아냈다. 이를 고치려면 너무 오랜 시간이 걸리고 힘들거라고 생각돼서 다른 사람의 풀이를 참조하기로 했다.

 

 

※ 다른 사람의 풀이

 

def solution(n):
	num = set(range(2, n+1))
	for i in range(2, n+1):
		if i in num:
			num -= set(range(2*i, n+1, i))
	return len(num)

 

에라토스테네스의 체를 사용하여 푼 방식이다. 프로그래머스 문제풀이에서 가장 많은 좋아요를 받은 풀이법이기도 하다. 소수를 구할 때 에라토스테네스의 체를 쓴다는 것은 알고 있었지만 미처 생각을 못한 것 같다. 우선 num에 2부터 n+1 까지의 rangeset를 저장시켜주고, i의 범위도 똑같이 설정시켜준다.

만약 inum 에 있을 경우, i 보다 한 배수 큰 숫자부터 n+1까지의 범위를 공차가 i 가 되게끔 하여 set를 구성한 후, num에서 빼준다.

마지막에는 num의 길이를 돌려주면 된다.