λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
3️⃣ Swift/Problem Solving

[Swift Algorithm] μŠ€νƒ μˆ˜μ—΄ BOJ #1874

by seolhee2750 2021. 8. 4.
문제 μ„€λͺ…

μŠ€νƒ (stack)은 기본적인 자료ꡬ쑰 쀑 ν•˜λ‚˜λ‘œ, 컴퓨터 ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•  λ•Œ 자주 μ΄μš©λ˜λŠ” κ°œλ…μ΄λ‹€. μŠ€νƒμ€ 자료λ₯Ό λ„£λŠ” (push) μž…κ΅¬μ™€ 자료λ₯Ό λ½‘λŠ” (pop) μž…κ΅¬κ°€ κ°™μ•„ 제일 λ‚˜μ€‘μ— λ“€μ–΄κ°„ μžλ£Œκ°€ 제일 λ¨Όμ € λ‚˜μ˜€λŠ” (LIFO, Last in First out) νŠΉμ„±μ„ 가지고 μžˆλ‹€.

1λΆ€ν„° nκΉŒμ§€μ˜ 수λ₯Ό μŠ€νƒμ— λ„£μ—ˆλ‹€κ°€ 뽑아 λŠ˜μ–΄λ†“μŒμœΌλ‘œμ¨, ν•˜λ‚˜μ˜ μˆ˜μ—΄μ„ λ§Œλ“€ 수 μžˆλ‹€. μ΄λ•Œ, μŠ€νƒμ— pushν•˜λŠ” μˆœμ„œλŠ” λ°˜λ“œμ‹œ μ˜€λ¦„μ°¨μˆœμ„ 지킀도둝 ν•œλ‹€κ³  ν•˜μž. μž„μ˜μ˜ μˆ˜μ—΄μ΄ μ£Όμ–΄μ‘Œμ„ λ•Œ μŠ€νƒμ„ μ΄μš©ν•΄ κ·Έ μˆ˜μ—΄μ„ λ§Œλ“€ 수 μžˆλŠ”μ§€ μ—†λŠ”μ§€, μžˆλ‹€λ©΄ μ–΄λ–€ μˆœμ„œλ‘œ push와 pop 연산을 μˆ˜ν–‰ν•΄μ•Ό ν•˜λŠ”μ§€λ₯Ό μ•Œμ•„λ‚Ό 수 μžˆλ‹€. 이λ₯Ό κ³„μ‚°ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λΌ.

 

μž…λ ₯

첫 쀄에 n (1 ≤ n ≤ 100,000)이 주어진닀. λ‘˜μ§Έ 쀄뢀터 n개의 μ€„μ—λŠ” μˆ˜μ—΄μ„ μ΄λ£¨λŠ” 1이상 nμ΄ν•˜μ˜ μ •μˆ˜κ°€ ν•˜λ‚˜μ”© μˆœμ„œλŒ€λ‘œ 주어진닀. λ¬Όλ‘  같은 μ •μˆ˜κ°€ 두 번 λ‚˜μ˜€λŠ” 일은 μ—†λ‹€.

 

좜λ ₯

μž…λ ₯된 μˆ˜μ—΄μ„ λ§Œλ“€κΈ° μœ„ν•΄ ν•„μš”ν•œ 연산을 ν•œ 쀄에 ν•œ κ°œμ”© 좜λ ₯ν•œλ‹€. push연산은 +둜, pop 연산은 -둜 ν‘œν˜„ν•˜λ„λ‘ ν•œλ‹€. λΆˆκ°€λŠ₯ν•œ 경우 NOλ₯Ό 좜λ ₯ν•œλ‹€.

 

λ‚΄ 문제 풀이

μž…λ ₯ 1

8
4
3
6
8
7
5
2
1

좜λ ₯1

+
+
+
+
-
-
+
+
-
+
+
-
-
-
-
-

 

μž…λ ₯2

5
1
2
5
3
4

좜λ ₯2

NO

 

λ‚΄ 문제 풀이
import Foundation

var n = Int(readLine()!)!

var point = Array(repeating: 0, count: n) // μˆ«μžλ³„λ‘œ μž…λ ₯λλŠ”μ§€ 확인
var max = 0 // μ§€κΈˆκΉŒμ§€ μž…λ ₯된 숫자 쀑 κ°€μž₯ 큰 수
var pre = 0
var result = [String]() // push, pop μ €μž₯
var answer = ""

for i in 0..<n {
    let num = Int(readLine()!)!
    
    point[num - 1] = 1
    
    // μž…λ ₯된 μˆ«μžκ°€ max보닀 클 λ•Œ
    if num > max {
        for _ in 0..<(num - max) {
            result.append("+")
        }
        result.append("-")
        pre = num
        max = num
    }
    
    // μž…λ ₯된 μˆ«μžκ°€ max보닀 μž‘μ„ λ•Œ
    else {
        // ν˜„μž¬ μž…λ ₯된 μˆ«μžμ™€ κ·Έ μ „ μž…λ ₯된 숫자 사이에 아직 popλ˜μ§€ μ•Šμ€ μˆ˜κ°€ μžˆλ‹€λ©΄, "NO"
        if point[((num - 1) + 1)...(pre - 1)].contains(0) {
            answer = "NO"
            break
        }
        
        else {
            result.append("-")
            pre = num
        }
    }
    
    if i == n - 1 {
        answer = result.joined(separator: "\n")
    }
}

print(answer)

μ²˜μŒμ—” μŠ€νƒ 배열을 λ§Œλ“€κ³ , 문제 κ·ΈλŒ€λ‘œ push, pop을 ν•΄μ€¬μ§€λ§Œ μ‹œκ°„μ΄ˆκ³Όκ°€ λ°œμƒν•˜μ—¬ λ‹€λ₯Έ 풀이 방법을 μ„ νƒν–ˆλ‹€.

풀이 방법을 μ •λ¦¬ν•œ 것을 μ²¨λΆ€ν•œλ‹€. πŸ‘‡

[문제 및 λ³€μˆ˜ μ„€λͺ…]

  • μž…μΆœλ ₯ 예제2λ²ˆμ„ λŒ€ν‘œλ‘œ μ˜ˆμ‹œλ₯Ό μž‘μ„±ν–ˆλ‹€.
  • 이 λ¬Έμ œμ—μ„œλŠ” 처음 n이 μž…λ ₯된 ν›„, μˆ˜μ—΄μ΄ ν•œ μˆ«μžμ”© μ°¨λ‘€λŒ€λ‘œ μž…λ ₯λœλ‹€.
    (ν•΄λ‹Ή μ˜ˆμ‹œμ—μ„œλŠ” n이 5, μˆ˜μ—΄μ€ 1 2 5 3 4)
  • 처음 μž…λ ₯된 n을 κΈ°μ€€μœΌλ‘œ, μ˜ˆμ‹œμ—μ„œλŠ” 5 크기의 point 배열을 μƒμ„±ν•΄μ£Όμ—ˆλ‹€.
    point 배열은 [0]이 1, [1]은 2, ..., [4]λŠ” 5λ₯Ό 가리킨닀고 κ°€μ •ν•˜μ—¬ μˆ˜μ—΄μ΄ μž…λ ₯λ˜λŠ” μˆœμ„œλŒ€λ‘œ
    μ–΄λ–€ μˆ˜κ°€ μž…λ ₯λ˜μ—ˆλŠ”μ§€ μ²΄ν¬ν•΄μ£ΌλŠ” 것이 이 point λ°°μ—΄μ˜ 역할이닀.
  • max λ³€μˆ˜λŠ” μ§€κΈˆκΉŒμ§€ μž…λ ₯된 μˆ˜μ—΄μ˜ μˆ˜λ“€ 쀑 κ°€μž₯ 큰 수λ₯Ό μ €μž₯ν•œλ‹€.
  • pre λ³€μˆ˜λŠ” ν˜„μž¬ μž…λ ₯된 수 λ°”λ‘œ 이전에 μž…λ ₯된 수λ₯Ό μ €μž₯ν•œλ‹€.
  • result 배열은 push, pop을 μ°¨λ‘€λŒ€λ‘œ μ €μž₯ν•œλ‹€.

[문제 풀이 κ³Όμ •]

  • λ¨Όμ € ν˜„μž¬ μž…λ ₯된 수 num이 max보닀 큰지 μž‘μ€μ§€λ₯Ό ν™•μΈν•œλ‹€.
  • μœ„ μ²¨λΆ€μ˜ (1), (2), (3)λ²ˆμ€ λͺ¨λ‘ num이 max보닀 큰 μƒν™©μ΄λ―€λ‘œ (3)λ²ˆμ„ λŒ€ν‘œλ‘œ μ„€λͺ…ν•˜κ² λ‹€.
  • num이 5μ΄λ―€λ‘œ point[4]μžλ¦¬μ— 5κ°€ λ“€μ–΄μ™”λ‹€λŠ” 의미둜 0을 1둜 λ°”κΏ”μ€€λ‹€.
  • maxλŠ” 이제 5μ΄λ―€λ‘œ max에 5λ₯Ό μ €μž₯ν•œλ‹€.
  • resultμ—λŠ” 이전 μž…λ ₯ 수인 preμ—μ„œ num을 λΊ€ 만큼 "+"λ₯Ό μΆ”κ°€ν•΄μ€€λ‹€. μ—¬κΈ°μ„œλŠ” 5 - 2μ΄λ―€λ‘œ "+" μ„Έκ°œ.
    그리고 ν•΄λ‹Ή μˆ˜μ—΄μ„ λ§Œλ“€κΈ° μœ„ν•΄μ„œλŠ” 5λ₯Ό popν–ˆλ‹€λŠ” 의미이기 λ•Œλ¬Έμ— ν•˜λ‚˜μ˜ "-"도 μΆ”κ°€ν•΄μ€€λ‹€.
  • μœ„μ˜ κ³Όμ •μœΌλ‘œ num이 5μž„μœΌλ‘œμ¨ ν•΄μ•Όν•  연산은 λ§ˆμ³€μœΌλ‹ˆ pre에 5λ₯Ό μ €μž₯ν•΄μ€€λ‹€.
  • κ·Έ λ‹€μŒ, (4)번 ν’€μ΄λ‘œ 가보면 λ“œλ””μ–΄ num이 max보닀 큰 상황이닀.
  • λ§ˆμ°¬κ°€μ§€λ‘œ 3이 μž…λ ₯λ˜μ—ˆμŒμ„ ν‘œμ‹œν•˜κΈ° μœ„ν•΄ point[2]에 1을 μ €μž₯ν•΄μ€€λ‹€.
  • 그리고 μ—¬κΈ°μ„œλŠ” max보닀 μˆ˜κ°€ μž‘μœΌλ―€λ‘œ, λ§ˆμ§€λ§‰ 수λ₯Ό popν–ˆμ„ λ•Œ ν•΄λ‹Ή num이 λ‚˜μ˜€μ§€ μ•ŠλŠ” 상황이 생길 수 μžˆλ‹€.
    이 λ•ŒλŠ” ν•΄λ‹Ή num보닀 더 크고, λ°”λ‘œ 이전에 pop된 수 사이에 popλ˜μ§€ μ•Šμ€ μˆ˜κ°€ μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•΄μ•Όν•œλ‹€.
    λ”°λΌμ„œ point[((num - 1) + 1)...(pre - 1)]. μ—¬κΈ°μ„œλŠ” point[3...3]에 0이 μžˆλŠ”μ§€ ν™•μΈν•œλ‹€.
    μ˜€λ¦„μ°¨μˆœμœΌλ‘œλ§Œ push되기 λ•Œλ¬Έμ— maxκΉŒμ§€μ˜ μˆ˜λŠ” 무쑰건 pushλ˜μ–΄μžˆλŠ” 것인데,
    0이 μžˆλ‹€λ©΄, 아직 popλ˜μ§€ μ•Šμ€ μˆ˜κ°€ μžˆλ‹€λŠ” 의미. λ”°λΌμ„œ μˆ˜μ—΄ λ§Œλ“€κΈ°κ°€ λΆˆκ°€ν•¨μ„ μ•Œ 수 μžˆλ‹€.
  • (λ§Œμ•½ μœ„μ˜ λ²”μœ„μ— 0이 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ num이 max보닀 클 λ•Œμ™€ λ™μΌν•˜κ²Œ μˆ˜ν–‰ν•œλ‹€.)

 

πŸ’‘ ν”Όλ“œλ°±
  • 배열을 계속 νƒμƒ‰ν•˜κ³  μΆ”κ°€, μ‚­μ œλ₯Ό 계속 ν•˜λ‹ˆ μ‹œκ°„μ΄ μ΄ˆκ³Όλœλ‹€.
  • μŠ€νƒ λ¬Έμ œλŠ” μ‰¬μš΄κ²ƒ κ°™μœΌλ©΄μ„œ,, μ‹œκ°„ μ΄ˆκ³Όλ˜λŠ” 일이 자주 μƒκΈ°λŠ” 것 κ°™λ‹€.
  • 효율적으둜 문제 풀이할 수 μžˆλŠ” 방법을 많이 곡뢀해야 ν•  것 κ°™λ‹€.

 


 

 

문제

https://www.acmicpc.net/problem/1874

λŒ“κΈ€