Skip to main content

πŸ“ 12921 μ†Œμˆ˜ μ°ΎκΈ°


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

1. 문제 μš”μ•½

  • 1λΆ€ν„° μž…λ ₯받은 숫자 n 사이에 있느 μ†Œμˆ˜μ˜ 개수 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜ μž‘μ„±ν•˜κΈ°
  • μ†Œμˆ˜ : 1κ³Ό 자기 μžμ‹ μœΌλ‘œλ§Œ λ‚˜λˆ„μ–΄μ§€λŠ” 수

2. 접근방법

  • boolean[] isPrime λ°°μ—΄ λ§Œλ“€μ–΄μ„œ 각 μˆ˜κ°€ μ†Œμˆ˜μΈμ§€ μ•„λ‹Œμ§€ 체크
    β†’ 보톡 μ†Œμˆ˜ νŒλ³„ν•˜λŠ” λ©”μ„œλ“œλ‚˜ 배열은 isPrime으둜 λ³€μˆ˜ λͺ…λͺ…ν•˜κΈ°
  • μ²˜μŒμ— 2 이상 λͺ¨λ“  수 μ†Œμˆ˜λΌκ³  κ°€μ •ν•˜κ³  μ‹œμž‘ν•˜κΈ°
    β†’ 0, 1은 μ†Œμˆ˜κ°€ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ΄λ‹€
  • 2 ~ 루트 nκΉŒμ§€ λŒλ©΄μ„œ 배수 μ œκ±°ν•˜κΈ°
  • μ΅œμ’…μ μœΌλ‘œ true둜 남아 μžˆλŠ” μˆ˜λ“€μ„ μΉ΄μš΄νŠΈν•˜λ©΄ 그게 μ†Œμˆ˜ 개수

3. μ •λ”₯μ½”λ“œ

class Solution {
    public int solution(int n) {
        
        boolean[] isPrime = new boolean[n + 1];
        
        // μ²˜μŒμ—λŠ” λͺ¨λ‘ true둜 두고 0. 1은 μ†Œμˆ˜κ°€ μ•„sλ‹ˆλ‹ˆκΉŒ μ œμ™Έ
        for (int i = 2; i <= n; i++) {
            isPrime[i] = true;
        }
        
        // μ—λΌν† μŠ€ν…Œλ„€μŠ€μ˜ 체
        for (int i = 2; i * i <= n; i++) {
            if (isPrime[i]) {
                for (int j = i * i; j <= n; j += i) {
                    isPrime[j] = false;
                }
            }
        }
        
        // μ†Œμˆ˜ 개수 μ„ΈκΈ°
        int count = 0;
        for (int i = 2; i <= n; i++) {
            if (isPrime[i]) count++;
        }
        
        return count;
    }
}

μ—λΌν† μŠ€ν…Œλ„€μŠ€μ˜ μ²΄μ—μ„œ λ²”μœ„κ°€ i*i <= nκΉŒμ§€λ§Œ μˆœνšŒν•˜λ©΄ λ˜λŠ” 이유?

  • μš°λ¦¬κ°€ μ†Œμˆ˜ νŒλ³„μ„ ν•  λ•Œ iλ₯Ό μ†Œμˆ˜λΌκ³  κ°€μ •ν•˜κ³  배수λ₯Ό μ§€μ›Œ λ‚˜κ°„λ‹€
  • μ—¬κΈ°κΉŒμ§€λ§Œ κ²€μ‚¬ν•˜λŠ” μ΄μœ λŠ” 루트 nμ΄ν›„μ˜ μˆ˜λŠ” 이전 μž‘μ€ μ†Œμˆ˜λ“€μ˜ λ°°μˆ˜μ—μ„œ λ‹€ 걸러쑌기 λ•Œλ¬Έμ΄λ‹€.

ν•©μ„±μˆ˜μ˜ νŠΉμ§•

μ–΄λ–€ 수 n이 ν•©μ„±μˆ˜λΌλ©΄, n = a * b 꼴둜 λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. 이 λ•Œ a 와 b 쀑 적어도 ν•˜λ‚˜λŠ” 루트 n μ΄ν•˜μ΄λ‹€.
  • 36 = 6 * 6
  • 91 = 7 * 13
  • 즉, 루트 nκΉŒμ§€λ§Œ κ²€μ‚¬ν•˜λ©΄ λͺ¨λ“  ν•©μ„±μˆ˜μ˜ μ•½μˆ˜ 쑰합을 컀버할 수 μžˆλ‹€.

(int j = i * i; j <= n; j += i μ—μ„œ i*i λΆ€ν„° κ²€μ‚¬ν•˜λŠ” 이유

  • i * iλŠ” n의 μ œκ³±κ·Όμ„ μ˜λ―Έν•œλ‹€.
  • 그리고 i * i 이상뢀터가 아직 μ•ˆ μ§€μ›Œμ§„ μƒˆλ‘œμš΄ 배수이기 λ•Œλ¬Έμ΄λ‹€.
  • μ΄λ ‡κ²Œ ν•˜λ©΄ 쀑볡 연산을 쀄일 수 μžˆλ‹€.

예λ₯Ό λ“€λ©΄, n = 30일 λ•Œ

  • i = 2라면 4, 6, 8, ... , 30 μ§€μ›Œμ§
  • i = 3μΌλ•Œ 9, 12, 15, ..., 30 μ§€μ›Œμ§

λ§Œμ•½μ— μ—¬κΈ°μ„œ i=6 λΆ€ν„° μ‹œμž‘ν•˜λ©΄

이미 6의 λ°°μˆ˜λŠ” μ•žμ—μ„œ λ‹€ μ§€μ›Œμ§ 12, 18, 24, 30은 λ‹€ μ§€μ›Œμ‘ŒκΈ° λ•Œλ¬Έμ—

λ”°λΌμ„œ i = 6μ΄ν›„λ‘œλŠ” μƒˆλ‘­κ²Œ μ§€μšΈ 게 μ—†λ‹€ κ·Έλž˜μ„œ i * i λΆ€ν„° μ§€μš°λ©΄ λœλ‹€.