본문으로 바로가기

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

 

1406번: 에디터

첫째 줄에는 초기에 편집기에 입력되어 있는 문자열이 주어진다. 이 문자열은 길이가 N이고, 영어 소문자로만 이루어져 있으며, 길이는 100,000을 넘지 않는다. 둘째 줄에는 입력할 명령어의 개수

www.acmicpc.net

해당 문제의 입력은 500,000이다

따라서 해당 문제는 O(n)의 시간복잡도로 충분히 풀 수 있다

var str = Array(readLine()!).map { String($0) }
let m = Int(readLine()!)!
var cursor = str.count

for _ in 0..<m {
    let command = readLine()!.split(separator: " ").map { String($0) }
    
    switch command[0] {
    case "L":
        if cursor > 0 {
            cursor -= 1
        }
    case "D":
        if cursor < str.count {
            cursor += 1
        }
    case "B":
        if cursor > 0 {
            str.remove(at: cursor - 1)
            cursor -= 1
        }
    case "P":
        str.insert(command[1], at: cursor)
        cursor += 1
    default: break
    }
}

let result = str.reduce("") {
    $0 + $1
}

print(result)

반복문을 한번밖에 사용하지 않았기때문에 이 코드의 시간복잡도는 O(n)일줄 알았다

하지만 시간초과로 문제를 틀렸다

 

이유를 곰곰히 생각해봤다

배열의 remove(at:) 및 insert(_:at:) 메서드는 시간복잡도가 O(n)이다

즉 위 코드의 시간복잡도는 O(n^2) 이 되는것이다

 

그래서 스택을 두개 만들어서 다시 구현을 했다

var left = Array(readLine()!)
var right = [Character]()

for _ in 0..<Int(readLine()!)! {
    let command = readLine()!
    
    switch command.first! {
    case "L":
        if !left.isEmpty {
            right.append(left.removeLast())
        }
    case "D":
        if !right.isEmpty {
            left.append(right.removeLast())
        }
    case "B":
        if !left.isEmpty {
            left.removeLast()
        }
    case "P":
        left.append(command.last!)
    default: break
    }
}

print(String(left + right.reversed()))

배열의 append(_:) 및 removeLast() 메서드는 시간복잡도가 O(1)이다

그렇기에 위 코드가 바로 O(n) 짜리 코드인것이다

 

내가 짠 코드뿐만이 아닌 언어에 구현되있는 메서드의 시간복잡도도 고려를 해야한다