Algorithm/πŸ‘ 문제

[Programmers] 징검닀리 κ±΄λ„ˆκΈ°

YURIπŸ•πŸ“πŸΆ 2021. 12. 18. 17:17
λ°˜μ‘ν˜•

μ§•κ²€λ‹€λ¦¬κ±΄λ„ˆκΈ°

카카였 μ΄ˆλ“±ν•™κ΅μ˜ "λ‹ˆλ‹ˆμ¦ˆ μΉœκ΅¬λ“€"이 "라이언" μ„ μƒλ‹˜κ³Ό ν•¨κ»˜ 가을 μ†Œν’μ„ κ°€λŠ” 쀑에 징검닀리가 μžˆλŠ” κ°œμšΈμ„ λ§Œλ‚˜μ„œ κ±΄λ„ˆνŽΈμœΌλ‘œ κ±΄λ„ˆλ €κ³  ν•©λ‹ˆλ‹€. "라이언" μ„ μƒλ‹˜μ€ "λ‹ˆλ‹ˆμ¦ˆ μΉœκ΅¬λ“€"이 λ¬΄μ‚¬νžˆ 징검닀리λ₯Ό 건널 수 μžˆλ„λ‘ λ‹€μŒκ³Ό 같이 κ·œμΉ™μ„ λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.

  • μ§•κ²€λ‹€λ¦¬λŠ” 일렬둜 놓여 있고 각 μ§•κ²€λ‹€λ¦¬μ˜ λ””λ”€λŒμ—λŠ” λͺ¨λ‘ μˆ«μžκ°€ μ ν˜€ 있으며 λ””λ”€λŒμ˜ μˆ«μžλŠ” ν•œ 번 λ°Ÿμ„ λ•Œλ§ˆλ‹€ 1μ”© μ€„μ–΄λ“­λ‹ˆλ‹€.
  • λ””λ”€λŒμ˜ μˆ«μžκ°€ 0이 되면 더 이상 λ°Ÿμ„ 수 μ—†μœΌλ©° μ΄λ•ŒλŠ” κ·Έ λ‹€μŒ λ””λ”€λŒλ‘œ ν•œλ²ˆμ— μ—¬λŸ¬ 칸을 κ±΄λ„ˆ λ›Έ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • 단, λ‹€μŒμœΌλ‘œ λ°Ÿμ„ 수 μžˆλŠ” λ””λ”€λŒμ΄ μ—¬λŸ¬ 개인 경우 무쑰건 κ°€μž₯ κ°€κΉŒμš΄ λ””λ”€λŒλ‘œλ§Œ κ±΄λ„ˆλ›Έ 수 μžˆμŠ΅λ‹ˆλ‹€.

"λ‹ˆλ‹ˆμ¦ˆ μΉœκ΅¬λ“€"은 개울의 μ™Όμͺ½μ— 있으며, 개울의 였λ₯Έμͺ½ κ±΄λ„ˆνŽΈμ— 도착해야 징검닀리λ₯Ό κ±΄λ„Œ κ²ƒμœΌλ‘œ μΈμ •ν•©λ‹ˆλ‹€.
"λ‹ˆλ‹ˆμ¦ˆ μΉœκ΅¬λ“€"은 ν•œ λ²ˆμ— ν•œ λͺ…μ”© 징검닀리λ₯Ό κ±΄λ„ˆμ•Ό ν•˜λ©°, ν•œ μΉœκ΅¬κ°€ 징검닀리λ₯Ό λͺ¨λ‘ κ±΄λ„Œ 후에 κ·Έ λ‹€μŒ μΉœκ΅¬κ°€ κ±΄λ„ˆκΈ° μ‹œμž‘ν•©λ‹ˆλ‹€.

λ””λ”€λŒμ— 적힌 μˆ«μžκ°€ μˆœμ„œλŒ€λ‘œ λ‹΄κΈ΄ λ°°μ—΄ stones와 ν•œ λ²ˆμ— κ±΄λ„ˆλ›Έ 수 μžˆλŠ” λ””λ”€λŒμ˜ μ΅œλŒ€ 칸수 kκ°€ λ§€κ°œλ³€μˆ˜λ‘œ μ£Όμ–΄μ§ˆ λ•Œ, μ΅œλŒ€ λͺ‡ λͺ…κΉŒμ§€ 징검닀리λ₯Ό 건널 수 μžˆλŠ”μ§€ return ν•˜λ„λ‘ solution ν•¨μˆ˜λ₯Ό μ™„μ„±ν•΄μ£Όμ„Έμš”.

[μ œν•œμ‚¬ν•­]

  • 징검닀리λ₯Ό κ±΄λ„ˆμ•Ό ν•˜λŠ” λ‹ˆλ‹ˆμ¦ˆ μΉœκ΅¬λ“€μ˜ μˆ˜λŠ” λ¬΄μ œν•œ 이라고 κ°„μ£Όν•©λ‹ˆλ‹€.
  • stones λ°°μ—΄μ˜ ν¬κΈ°λŠ” 1 이상 200,000 μ΄ν•˜μž…λ‹ˆλ‹€.
  • stones λ°°μ—΄ 각 μ›μ†Œλ“€μ˜ 값은 1 이상 200,000,000 μ΄ν•˜μΈ μžμ—°μˆ˜μž…λ‹ˆλ‹€.
  • kλŠ” 1 이상 stones의 길이 μ΄ν•˜μΈ μžμ—°μˆ˜μž…λ‹ˆλ‹€.

예제

stones : [2, 4, 5, 3, 2, 1, 4, 2, 5, 1]    
k : 3

answer 
3

풀이

λ§Œμ•½ 5λͺ…μ˜ λ‹ˆλ‹ˆμ¦ˆ μΉœκ΅¬λ“€μ΄ 징검닀리λ₯Ό λͺ¨λ‘ 건널 수 μžˆλŠ”μ§€ μ•Œμ•„λ³΄κΈ° μœ„ν•΄μ„œλŠ” μ²˜μŒλΆ€ν„° λ§ˆμ§€λ§‰κΉŒμ§€ κ±΄λ„ˆκ²Œ ν•΄λ³΄λŠ” 게 μ•„λ‹ˆλΌ, κ°€μž₯ λ§ˆμ§€λ§‰μΈ λ‹€μ„―λ²ˆμ§Έκ°€ 건널 수 μžˆλ‹€λ©΄ 5λͺ…이 징검닀리λ₯Ό 건널 수 μžˆλŠ” 것이기 λ•Œλ¬Έμ— λ‹€μ„―λ²ˆμ§Έμ˜ λ‹ˆλ‹ˆμ¦ˆκ°€ 건널 수 μžˆλŠ”μ§€λ§Œ 보면 λœλ‹€.

즉 μš°λ¦¬λŠ” n번째 λ‹ˆλ‹ˆμ¦ˆκ°€ 건널 수 μžˆλŠ”μ§€ νŒλ‹¨ν•˜κ³ , 건널 수 μžˆλ‹€λ©΄ ν˜„μž¬ μ΅œλŒ€ nλͺ…μ˜ λ‹ˆλ‹ˆμ¦ˆκ°€ 건널 수 μžˆλ‹€κ³  μƒκ°ν•˜λ©΄ λœλ‹€.

μ΄λ•Œ 이 λ¬Έμ œμ—μ„œ 징검닀리λ₯Ό κ±΄λ„ˆμ•Ό ν•˜λŠ” λ‹ˆλ‹ˆμ¦ˆ μΉœκ΅¬λ“€μ˜ μˆ˜λŠ” λ¬΄μ œν•œμ΄μ§€λ§Œ stones λ°°μ—΄μ˜ 각 μ›μ†Œμ˜ 값은 1λΆ€ν„° 200,000,000μ΄ν•˜μ΄κΈ° λ•Œλ¬Έμ— μ΅œλŒ€λ‘œ 건널 수 μžˆλŠ” λ‹ˆλ‹ˆμ¦ˆ 친ꡬ의 μˆ˜λŠ” 1λΆ€ν„° 200,000,000이 λœλ‹€.
(λͺ¨λ“  λ””λ”€λŒμ˜ μˆ«μžκ°€ 200,000,000이라고 μƒκ°ν–ˆμ„ λ•Œ)

즉, n(n번째 λ‹ˆλ‹ˆμ¦ˆ)은 1λΆ€ν„° 200,000,000이 될 수 있고 이뢄 탐색을 μ΄μš©ν•΄μ„œ n의 λ²”μœ„λ₯Ό μ°¨μ°¨ μ€„μ—¬κ°€λ©΄μ„œ μ§„ν–‰ν•˜λ©΄ λœλ‹€.

상세 풀이

n번째 λ‹ˆλ‹ˆμ¦ˆ μΉœκ΅¬κ°€ 징검닀리λ₯Ό 건널 λ•Œ λ””λ”€λŒμ˜ 상황은 λ‹€μŒκ³Ό κ°™λ‹€.

  • n번째 λ‹ˆλ‹ˆμ¦ˆ μΉœκ΅¬κ°€ 징검닀리λ₯Ό κ±΄λ„ˆλŠ” 상황이라면(n-1λ²ˆμ§ΈκΉŒμ§€λŠ” λͺ¨λ‘ κ±΄λ„œλ‹€κ³  κ°€μ •) ν˜„μž¬ μ§•κ²€λ‹€λ¦¬μ˜ 상황은 λ””λ”€λŒμ— 적힌 숫자 - (n-1)이 λœλ‹€.
처음

2 4 5 3 2 1 4 2 5 1

4번째 λ‹ˆλ‹ˆμ¦ˆκ°€ κ±΄λ„ˆλŠ” 상황

0 1 2 0 0 0 1 0 2 0

λ””λ”€λŒμ˜ μˆ«μžκ°€ 0이 되면 더 이상 λ°Ÿμ„ 수 μ—†μ§€λ§Œ ν•œ λ²ˆμ— kμΉΈκΉŒμ§€ κ±΄λ„ˆλ›Έ 수 μžˆλ‹€.

  • for문을 λŒλ©΄μ„œ stones[current_idx] - n < 0 인지 νŒλ‹¨ν•˜κ³  0μ΄ν•˜λΌλ©΄ cntλ₯Ό λŠ˜λ¦°λ‹€. 건널 수 μ—†λŠ” λ””λ”€λŒμ΄ k만큼 λΆ™μ–΄ μžˆλ‹€λ©΄(cnt == k) 더이상 κ±΄λ„ˆκ°ˆ 수 μ—†κΈ° λ•Œλ¬Έμ— νƒμƒ‰μ˜ λ²”μœ„λ₯Ό μ•žμœΌλ‘œ μ€„μ—¬μ„œ(right = mid -1) λ‹€μ‹œ μ§„ν–‰ν•˜λ©΄ λœλ‹€.

λ§Œμ•½ n번째 λ‹ˆλ‹ˆμ¦ˆκ°€ λͺ¨λ“  λ””λ”€λŒμ„ κ±΄λ„œλ‹€λ©΄, 더 뒀에 μˆœμ„œμ— μžˆλŠ” λ‹ˆλ‹ˆμ¦ˆ(n보닀 큰)κ°€ λ””λ”€λŒμ„ 건널 μˆ˜λ„ 있기 λ•Œλ¬Έμ— νƒμƒ‰μ˜ μ‹œμž‘μ„ n+1(left = mid+1)둜 ν•˜κ³  λ‹€μ‹œ μ§„ν–‰ν•œλ‹€. 그리고 μ΄λ•Œ μ΅œλŒ€λ‘œ 건널 수 μžˆλŠ” λ‹ˆλ‹ˆμ¦ˆμ˜ 수λ₯Ό λ‹€μ‹œ μ„€μ •ν•œλ‹€.

μ½”λ“œ

public int solution(int[] stones, int k) {
    int answer = 0;
    int min = 1;
    int max = 200000000;

    // 이뢄탐색을 μ΄μš©ν•΄μ„œ n의 λ²”μœ„λ₯Ό 쀄여간닀.
    while (min <= max) {
        int currentIdx = (min + max) / 2;
        int zeroCnt = 0;
        boolean isSuccessful = true;

        for (int stone : stones) {
            if (stone - currentIdx < 0) { // currentIdx번째둜 징검닀리λ₯Ό 건널 λ•Œ λ””λ”€λŒμ˜ μƒνƒœκ°€ 0μ΄ν•˜λΌλ©΄
                zeroCnt++; // κ±΄λ„ˆμ§€ λͺ»ν•˜λŠ” λ””λ”€λŒμ΄μ—¬μ„œ cntλ₯Ό μ¦κΈ°μ‹œν‚¨λ‹€
            } else { // 건널 수 μžˆλ‹€λ©΄
                zeroCnt = 0;
            }
            if (zeroCnt == k) { // λ§Œμ•½, μ—°μ†μœΌλ‘œ k만큼 κ±΄λ„ˆμ§€ λͺ»ν•˜λŠ” λ””λ”€λŒμΌ λ•Œ
                max = currentIdx - 1; // 탐색 λ²”μœ„λ₯Ό 쀄인닀
                isSuccessful = false;
                break;
            }
        }

        if (isSuccessful) { // currentIdx번째의 λ‹ˆλ‹ˆμ¦ˆκ°€ κ±΄λ„œλ‹€λ©΄
            min = currentIdx + 1;
            answer = currentIdx; // ν˜„μž¬ κΈ°μ€€μœΌλ‘œ μ΅œλŒ€ currentIdxλͺ…μ˜ λ‹ˆλ‹ˆμ¦ˆκ°€ 건널 수 μžˆλ‹€.
        }
    }
    return answer;
}    
λ°˜μ‘ν˜•