문제

https://programmers.co.kr/learn/courses/30/lessons/12977


코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public int solution(int[] nums) {
int answer = 0;

List<Long> list = getSumList(nums);

for (long i : list) {
boolean isNotPrime = false;
for (int j = 2; j * j <= i; j++) {
if (i % j == 0) {
isNotPrime = true;
break;
}
}

if (!isNotPrime) {
++answer;
}
}

return answer;
}

private List<Long> getSumList(int[] nums) {
List<Long> list = new ArrayList<Long>();

int arrayLength = nums.length;
for (int i = 0; i < arrayLength; i++) {
for (int j = i + 1; j < arrayLength; j++) {
if (j == arrayLength - 1) {
break;
}

for (int k = j + 1; k < arrayLength; k++) {
list.add((long) (nums[i] + nums[j] + nums[k]));
}
}
}

return list;
}

흐름

  1. 3개이므로 3중 for문으로 돌면서 경우의 수 모두 돌면서 더한 값을 list에 저장
  2. arrayoutofrange가 발생하지 않도록 length -1 인 경우 끝냄
  3. 모든 합이 저장된 list를 돌면서 소수인지 확인함
  4. 구한 값이 소수이면 값을 증가시킴
  5. 반복이 끝나면 return

결과

번호 속도
테스트 1 통과 (2.48ms, 52.7MB)
테스트 2 통과 (3.29ms, 52.2MB)
테스트 3 통과 (1.36ms, 52.4MB)
테스트 4 통과 (1.32ms, 52.8MB)
테스트 5 통과 (4.94ms, 50.4MB)
테스트 6 통과 (5.02ms, 52.3MB)
테스트 7 통과 (1.10ms, 53MB)
테스트 8 통과 (8.70ms, 52.2MB)
테스트 9 통과 (1.78ms, 52.1MB)
테스트 10 통과 (8.33ms, 52.5MB)
테스트 11 통과 (1.06ms, 52.1MB)
테스트 12 통과 (0.95ms, 52.3MB)
테스트 13 통과 (1.03ms, 50.5MB)
테스트 14 통과 (0.94ms, 52.4MB)
테스트 15 통과 (0.82ms, 50MB)
테스트 16 통과 (8.65ms, 52.8MB)
테스트 17 통과 (7.43ms, 52.4MB)
테스트 18 통과 (0.95ms, 52.9MB)
테스트 19 통과 (0.83ms, 50.3MB)
테스트 20 통과 (9.97ms, 52.5MB)
테스트 21 통과 (10.12ms, 52.6MB)
테스트 22 통과 (2.31ms, 52.3MB)
테스트 23 통과 (0.83ms, 52.1MB)
테스트 24 통과 (9.64ms, 50.8MB)
테스트 25 통과 (9.52ms, 50.5MB)
테스트 26 통과 (0.89ms, 52.1MB)

테스트 케이스

1
2
assertEquals(1, test.solution(new int[] {1,2,3,4}));
assertEquals(4, test.solution(new int[] {1,2,7,6,4}));

여담

당연히 속도 제한에 걸릴 줄 알고 제출했는데 통과되었다
썩 만족스럽지 못한 코드
만약 서로 다른 3개가 아니라 임의 수 n 이었다면?
고민을 좀 더 해봐야 할 듯 싶다.

댓글 공유

문제

https://programmers.co.kr/learn/courses/30/lessons/12921


코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public int solution(int n) {
boolean[] prime = new boolean[n+1];

prime[0] = true;
prime[1] = true;

for (int i = 2; (i * i) <= n; i++) {
if (!prime[i]) {
for (int j = i * 2; j <= n; j += i) {
prime[j] = true;
}
}
}

int answer = 0;
for (boolean is : prime) {
if (!is) {
answer++;
}
}

return answer;
}

흐름

  • 에라토스테네스의 체로 해결

Sieve_of_Eratosthenes_animation

  1. n까지의 숫자중 0과 1은 소수가 아니므로 true 할당
  2. 2부터 루트n 까지 반복하면서 배수들에 true 할당
  3. 소수 판별한 배열 prime을 loop 돌면서 false 인 경우에만 갯수 추가

부연 설명

1
for (int i = 2; (i * i) <= n; i++)

입력받은 수 n이 합성수 인 경우 $$n = a * b​$$ 로 나타낼 수 있다.
이 때 a와 b 중 큰거나 같은 수를 a, 작거나 같은 수를 b라고 가정하면 b가 a보다 작으므로 $$ a * a >= a * b $$ 이고
$$ n = a * b $$ 이므로, 큰 수 a의 제곱일 경우 $$ a^2>=n $$ 처럼 된다.
이를 치환하면 $$ a>=\sqrt{n} $$ 이 되므로 a의 최솟값은 $$ \sqrt{n} $$ 이 된다.
그리고 b는 $$ a >= b $$이므로 b의 최댓값은 $$ \sqrt{n} $$ 이 된다.
고로 n이 소수가 아닌 합성수라면 a의 와 b의 합성수로 이루어 짐을 알 수 있으므로, $$ \sqrt{n} $$ 까지만 반복하면 소수임을 판별할 수 있다.

  • ex) 입력받은 수 n이 50일 경우 $$ \sqrt{50} $$ = 7.071067811865475‬‬….이므로, 7.071067811865475‬‬… 을 기준으로 50의 약수 {1,2,5,10,25,50}을 나누면 b = {1, 2, 5}, a = {10, 25, 50} 이므로 b만 검사하면 50이 소수 인지 아닌지 알 수 있다.
1
for (int j = i * 2; j <= n; j += i)

원래는 i보다 작은 수인 경우 이미 이전에 작은 수 * i에서 삭제된 상태이므로 i * i인 게 맞으나,
i의 값이 너무 클 경우 문제가 될 수 있으므로 $$ i * 2 $$ 로 설정한다.
물론 이 문제에선 100만 까지로 한정되어 있으므로 $$ i * i $$ 를 해도 문제는 없다.


참고 사이트

댓글 공유

  • page 1 of 1

Junggu Ji

author.bio


author.job