Swift Algorithm 프로그래머스 Lv2 타겟넘버

지난 BFS글에서 아래 코드를 참고하면,

node.0 (해당 노드의 값) 을 이용하여 해당 노드를 방문한적이 있는지를 판단하였다.


각 노드의 값이 해당 노드의 개수까지 정확히 1씩 증가한다면 해당 풀이가 틀리지 않겠지만 사실 현실은 그렇지 않다.

var graph: [[(Int, Int)]] = [
    [(2, 1), (3, 1)],
    [(1, 1), (4, 1), (5, 1)],
    [(1, 1)],
    [(2, 1)],
    [(2, 1)]
]

var visited: [Bool] = Array.init(repeating: false, count: graph.count)

func dfs(startIndex: Int) {
    visited[startIndex] = true
    
    for node in graph[startIndex] {
        if !visited[node.0 - 1] {
            print(node.0)
            dfs(startIndex: node.0 - 1)
        }
    }
}

dfs(startIndex: 0)


그렇기 때문에 Dictionary를 이용하여, key를 방문하였는지 / 안하였는지를 체킹하는 방식도 소개한다.

위에서 말한 현실은 그렇지 않다 를 만족하는 문제가 있는데, 타겟넘버 문제이다.


해당 문제에서는 [1,1,1,1,1] 과 같은 숫자가 들어왔을때, 이 수의 순서를 유지한 상태로 더하거나 빼서 타겟넘버를 맞추는 개수를 구하는 문제이다.

따라서, [1,1,1,1,-1]과 같은 식의 접근을 할 수 있는데, 이때 위의 방식대로 각 원소를 인덱스에 대입해서 푼다면 오류가 발생하게 된다.



따라서 이번엔, Dictionary의 key를 이용하여 dfs를 진행해보고자 하였다.

+원소, -원소 두가지의 자식 노드를 가진 부모노드가 아래로 numbers의 개수만큼 뻗어나가기 때문에 이를 이용해서 key를 가지는 graph 형태를 만들어주었다.

(다음 원소를 반드시 방문 할 수 있도록 재귀적 형태를 만들어 주어서, visited가 필요 없게 되었다.)


graph[startId] 의 노드들은 결국 최초 방문 노드의 다음 인덱스의 노드 이기 때문에 이를 통해 깊이우선 탐색을 진행할 수 있다.

import Foundation

func solution(_ numbers:[Int], _ target:Int) -> Int {
    var graph: [Int: [(Int, Int)]] = [:]
    var resultList: [[Int]] = []
    
    for (i, n) in numbers.enumerated() {
        graph[i] = [(n, 1), (-n, 1)]
    }
    
    func dfs(startId: Int, path: [(Int, Int)]) {
        if startId == graph.count { 
            resultList.append(path.map { $0.0 })
            return
        }
        
        for node in graph[startId]! {
            let newPath = path + [node]
            dfs(startId: startId + 1, path: newPath)
        }
        
    }
    
    dfs(startId: 0, path: [])
    return resultList.map{ $0.reduce(0, +) }.filter { $0 == target }.count
}


사실 해당 방식은 굉장히 비효율적인 방식이다. 굳이 저장하지 않고 targetNumber의 판단이 가능하지만 resultList에 해당 값들을 대입하게 되어 불필요한 메모리를 사용하게 된다.

다만, 어떤식으로 탐색이 이루어지는지를 볼 수 있기 때문에 우선은 해당 방식으로 구현하였다.


조금 다듬어서, 코드를 작성한다면 다음과 같다.

import Foundation

func solution(_ numbers:[Int], _ target:Int) -> Int {
    var graph: [Int: [(Int, Int)]] = [:]
    var targetNumCount: Int = 0
    
    for (i, n) in numbers.enumerated() {
        graph[i] = [(n, 1), (-n, 1)]
    }
    
    func dfs(startId: Int, path: [(Int, Int)], result: Int) {
        if startId == graph.count { 
            if result == target {
                targetNumCount += 1
            }
            return
        }
        
        for node in graph[startId]! {
            let newPath = path + [node]
            dfs(startId: startId + 1, path: newPath, result: node.0 + result)
        }
        
    }
    
    dfs(startId: 0, path: [], result: 0)
    return targetNumCount
}

실행속도 변화


최신 아티클
[1] Swift Algorithm DFS
박익범
|
2025.04.22
[1] Swift Algorithm DFS
Swift Algorithm 프로그래머스 Lv1 체육복
박익범
|
2025.04.21
Swift Algorithm 프로그래머스 Lv1 체육복