프로그래머스 LV1 - 카드뭉치(Swift)

2023. 3. 14. 20:43알고리즘 문제

반응형

접근방식

  • 큐를 이용하여 현재 가장 첫번째 원소가 현재 cards1 혹은 cards2에 위치하는지 확인 후 있을 경우 goal을 계속 확인
  • 없을 경우, 곧바로 return
  • goal의 모든 항목이 cards1cards2에 있는지 확인한다.

첫번째 정답

func haveWord(_ cards1:[String], _ cards2:[String], _ goal:[String]) -> Bool {
    var result = false

    goal.forEach { word in
        if cards1.contains(word) || cards2.contains(word) {
            result = true
        } else {
            result = false
            return
        }
    }

    return result
}

func solution(_ cards1:[String], _ cards2:[String], _ goal:[String]) -> String {
    if haveWord(cards1, cards2, goal) == false {
        return Result.failure.value
    }

    var cards1 = cards1
    var cards2 = cards2
    var result: Result = .success

    goal.forEach { word in
        if cards1.first == word {
            cards1.removeFirst()
        } else if cards2.first == word {
            cards2.removeFirst()
        } else {
            result = .failure
            return
        }
    }

    return result.value
}

  • 위 문제를 푼 이후 든 생각
    1. 굳이 haveWord 메소드를 할 필요가 없다. - 만약 없을 경우 큐의 첫번째 원소에서도 없을거기 때문에 굳이 for문이 여러번 도는 방식을 만들 필요가 없다.
    2. removeFirst의 시간복잡도는 O(n)이므로 LinkedList를 통하여 Queue를 만들어줄 필요가 있을 것 같다.

두번째 정답

enum Result {
    case success
    case failure

    var value: String {
        switch self {
        case .success:
            return "Yes"
        case .failure:
            return "No"
        }
    }
}

class Node {
    let value: String
    var next: Node?

    init(value: String, next: Node? = nil) {
        self.value = value
        self.next = next
    }
}

struct LinkedList {
    var head: Node?
    var tail: Node?
    var peek: String? {
        return self.head?.value
    }

    init(data: [String]) {
        data.forEach { word in
            let node = Node(value: word)

            if head == nil && tail == nil {
                self.head = node
                self.tail = node
            } else {
                self.tail?.next = node
                self.tail = node
            }
        }
    }

    mutating func removeFirst() {
        let firstNode = self.head

        self.head = firstNode?.next

        firstNode?.next = nil
    }
}

func solution(_ cards1:[String], _ cards2:[String], _ goal:[String]) -> String {
    var cards1 = LinkedList(data: cards1)
    var cards2 = LinkedList(data: cards2)
    var result: Result = .success

    goal.forEach { word in
        if cards1.peek == word {
            cards1.removeFirst()
        } else if cards2.peek == word {
            cards2.removeFirst()
        } else {
            result = .failure
            return
        }
    }

    return result.value
}

  • LinkedList를 통한 Queue구현 및 haveWord메소드를 없애므로써 시간이 이전 정답에 비해 확 줄어들었다.
  • 또한 YesNo를 굳이 String값으로 가지고 있을 필요가 없기 때문에 열거형으로 구현하여 Result타입을 통해 값을 리턴해주었다.
반응형