본문 바로가기

프로그래머스 PS일지/level3

[프로그래머스][Swift] 표 편집 - Level3

 

프로그래머스 표 편집[링크]

간단한 문제 요약

명령어 기반으로 표의 행을 선택, 삭제, 복구하는 과제를 맡았다. 파란색으로 칠해진 칸이 현재 선택된 행이고, 한 번에 한 행만 선택할 수 있구 표의 범위를 벗어날 수 없다.

  • "U X": 현재 선택된 행에서 X칸 위에 있는 행을 선택합니다.
  • "D X": 현재 선택된 행에서 X칸 아래에 있는 행을 선택합니다.
  • "C" : 현재 선택된 행을 삭제한 후, 바로 아래 행을 선택합니다. 단, 삭제된 행이 가장 마지막 행인 경우 바로 윗 행을 선택합니다.
  • "Z" : 가장 최근에 삭제된 행을 원래대로 복구합니다, 현재 선택된 행은 바뀌지 않습니다.

문제 풀이

어떻게 삭제한 정보를 가져올 수 있을까?, 어떻게 삭제하지 않은 행들만 탐색할 수 있을까?, 답 출력할 때 어떻게 행들의 삭제여부를 표시할 수 있을까?

 

이들을 표시해야합니다.

 

배열을 통해서, 행들의 삭제여부를 체크할 수 있고, 연결리스트의 노드를 통해서 삭제하지 않은 행들만 탐색할 수 있습니다. 뒤로가기 기능은 스택을 통해서 표시할 수 있게됩니다.

 

 

모든 노드 각각은 prev, next를 통해 위 아래를 가리켜야하고, 노드가 제거될 때 아래 위 노드만 서로 연결해주고, 삭제할 노드는 스택에 추가합니다. 이때 삭제된 여부를 변경합니다. 삭제된 노드를 되돌리기할 때는, 스택에서 가장 최근에 삭제된 노드를 가져와 해당 노드가 참조했던 상, 하 노드에서 자신을 가리키도록 다시 표기합니다.

코드

/// 노드는 테이블의 한 행을 의미합니다. 한 행은 위, 아래 행을 참조할 수 있습니다.
final class Node {
  var prev: Node?
  var next: Node?
  var isDeleted: Bool = false
}

 

func solution(_ n:Int, _ k:Int, _ cmd:[String]) -> String {
  /// 참조가 되지 않고 각자 독립적인 노드가 만들어질 수 있도록 유의해야합니다.
  var nodes = (0..<n).map { _ in Node() }
  /// 삭제된 노드는 stack처럼 활용해서 push, pop합니다.
  var removedBuf: [Node] = []
  /// 현재 노드를 통해서, 연결된 노드들의 위치들만 탐색합니다.
  var curNode = nodes[k]
  for i in 1..<n {
    nodes[i-1].next = nodes[i]
    nodes[i].prev = nodes[i-1]
  }
  for command in cmd {
    let splitted = command.split{$0==" "}.map { String($0) }
    switch splitted[0] {
    case "U": /// 위로!
      let x = Int(splitted[1])!
      for _ in 0..<x {
        guard let prev = curNode.prev else { break }
        curNode = prev
      }
    case "D": /// 아래로!
      let x = Int(splitted[1])!
      for _ in 0..<x {
        guard let next = curNode.next else { break }
        curNode = next
      }
    case "C": /// 삭제하기
      curNode.isDeleted = true
      removedBuf.append(curNode)
      curNode.prev?.next = curNode.next
      curNode.next?.prev = curNode.prev
      curNode = curNode.next ?? curNode.prev!
    default: /// 꺼내기!
      let popped = removedBuf.popLast()
      popped?.isDeleted = false
      popped?.next?.prev = popped
      popped?.prev?.next = popped
    }
  }
  return nodes.map { $0.isDeleted ? "X" : "O" }.joined()
}