1. ํ๊ฒ ๋๋ฒ (DFS)
- 1์ ๋ํ๊ฑฐ๋ ๋บ ์ ์๊ธฐ ๋๋ฌธ์, ๋ํ๊ฑฐ๋ ๋นผ๋ ๊ฒฝ์ฐ์ ๋ํด ํ๋ฒ์ฉ DFS ๋ฅผ ์ํํด์ค๋ค.
- ์ด๋ฅผ ๊ทธ๋ํ๋ก ๊ทธ๋ ค๋ณด๋ฉด ์ดํดํ๊ธฐ ์ฝ๋ค. ์ซ์๋ฅผ ํ๋ ๋ํ๊ฑฐ๋ ๋นผ๋ ๊ฒ์ ๊ทธ๋ํ์ ๊น์ด ํ์์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.
import Foundation
func dfs(numbers: [Int], target: Int, i: Int, total: Int) -> Int {
if i == numbers.count {
return total == target ? 1 : 0
}
let count1 = dfs(numbers: numbers, target: target, i: i+1, total: total - numbers[i])
let count2 = dfs(numbers: numbers, target: target, i: i+1, total: total + numbers[i])
return count1 + count2
}
func solution(_ numbers:[Int], _ target:Int) -> Int {
return dfs(numbers: numbers, target: target, i: 0, total: 0)
}
2. ๋คํธ์ํฌ (DFS)
- ๊ฐ ์ปดํจํฐ๋ฅผ ๋ ธ๋๋ก, ์ปดํจํฐ๊ฐ ์ฐ๊ฒฐ๋ ๋คํธ์ํฌ๋ฅผ ๊ทธ๋ํ๋ก ์๊ฐํ๋ฉด ๋๋ค.
- ํน์ ์ปดํจํฐ์์ ์์ํด ์ฐ๊ฒฐ๋ ๋ชจ๋ ์ปดํจํฐ๋ฅผ ํ์ํ๋ DFS ๋ฐฉ์์ ์ด์ฉํ๋ค.
- visited ๋ฐฐ์ด์ ํตํด ๋ฐฉ๋ฌธํ ๋ ธ๋๋ฅผ ์ฒดํฌํ ํ, ํ์ํ๋๋ก ํ๋ค.
- DFS ๋ฅผ ์ด ๋ช๋ฒ ์ํํ๋์ง ์ฒดํฌํ๋ฉด ๋คํธ์ํฌ์ ๊ฐ์๋ฅผ ์ฐพ์ ์ ์๋ค.
import Foundation
// ๋คํธ์ํฌ ๊ฐ์๋ฅผ return -> DFS ๋ก ๊ฐ์ ๋คํธ์ํฌ ์ ๋ถ ์ฒดํฌ
// computers[i][j] : i๋ฒ๊ณผ j๋ฒ์ด ์ฐ๊ฒฐ๋์ด์์ผ๋ฉด 1, ์๋๋ฉด 0
func dfs(_ graph: [[Int]], _ visited: inout [Bool], _ i: Int) {
if i == graph.count {
return
}
visited[i] = true
for (j, isConnect) in graph[i].enumerated() {
if isConnect == 1 && !visited[j] {
dfs(graph, &visited, j)
}
}
}
func solution(_ n:Int, _ computers:[[Int]]) -> Int {
var visited = Array(repeating: false, count: n)
var count = 0
for i in 0..<n {
if visited[i] == false {
dfs(computers, &visited, i)
count += 1
}
}
return count
}
3. ๋จ์ด ๋ณํ (BFS)
- begin ๋จ์ด๋ words ๋ฐฐ์ด์ ์์ด, ์ด๋ฅผ ์ถ๊ฐํด์ฃผ์๋ค.
- ์ฐธ๊ณ ๋ก target ์ด words ์ ์๋ค๋ฉด begin -> target ์ด ๋ถ๊ฐ๋ฅํ๋ฏ๋ก 0 ์ ๋ฐํํ๋ค.
- ์ฃผ์ด์ง words ๋ฅผ ํตํด ์ด์ ๊ทธ๋ํ๋ฅผ ๋ง๋ค์๋ค. ๋จ์ด๊ฐ ํ๋๋ง ์ฐจ์ด๋๋ ๋จ์ด๋ค์ ์ฐ๊ฒฐํด์ฃผ๋ ๊ทธ๋ํ์ด๋ค. (๋จ์ด 50๊ฐ์ดํ)
- ์ด์ ๊ทธ๋ํ์ ๋ํด BFS ๋ฅผ ์ํํ๋ค. ๊ฐ์ฅ ์งง์ ๋ณํ ๊ณผ์ ์ ์ฐพ๋๊ฒ์ด๊ธฐ ๋๋ฌธ์ BFS ๋ฅผ ์ํํ๋ค.
- depth ๊ณ์ฐ์ ํ์ฌ ๋ ธ๋์์ ์ฐ๊ฒฐ๋ ๋ ธ๋๋ค์ queue ์ ๋ฃ์ด์ค ๋, ํ์ฌ ๋ ธ๋์ depth + 1 ๋ก ๊ณ์ฐํด์ค๋ค.
- ๋ ธ๋๋ฅผ ๋ฐฉ๋ฌธํ๋๋๋ก ๋จ์ํ ๊ณ์ฐํด์ค๋ค๋ฉด, depth ๋ฅผ ๊ณ์ฐํ ์ ์๋ค. (์ค๋ฅธ์ชฝ ๊ทธ๋ฆผ์ ๊ฒ์์์ด ์ด์ ํด๋น, ๋นจ๊ฐ์์ด Depth)
- ํด๋น ๋ฌธ์ ์์๋ ํ ์คํธ 1๋ฒ์ด ํต๊ณผํ์ง ๋ชปํด๋, ์ฑ์ ์ด ๊ฐ๋ฅํ ์๋ฌ๊ฐ ์๋ค. (1๋ฒ๋ ํต๊ณผ๋์ด์ผ ๋ง๋ ํ์ด๋ค ..!)
func getNeighbours(_ words: [String]) -> [[Int]] {
let n = words.count
var neighbours = Array(repeating: [Int](), count: n)
for i in 0..<n {
for j in i+1..<n {
var count = 0
zip(words[i], words[j]).forEach { (c1, c2) in
if c1 != c2 { count += 1 }
}
if count == 1 {
neighbours[i].append(j)
neighbours[j].append(i)
}
}
}
return neighbours
}
/// BFS
func findShortestPath(_ neighbours: [[Int]], _ words: [String], _ target: String) -> Int {
let n = neighbours.count
var queue = [Int]()
var depth = Array(repeating: 0, count: n)
var visited = Array(repeating: false, count: n)
queue.append(0)
visited[0] = true
while !queue.isEmpty {
let current = queue.removeFirst()
if words[current] == target {
return depth[current]
}
for next in neighbours[current] {
if visited[next] == false {
visited[next] = true
depth[next] = depth[current] + 1
queue.append(next)
}
}
}
return 0
}
func solution(_ begin:String, _ target:String, _ words:[String]) -> Int {
// Step0. ๋น๊ธด๋ ๋จ์ด์ ์ถ๊ฐ, ํ๊ฒ์ด ์๋ ๊ฒฝ์ฐ ๋ง๋ค ์ ์์
guard words.contains(target) else {
return 0
}
var words = words
words.insert(begin, at: 0)
// Step1. ์ํ๋ฒณ ํ๋๋ฅผ ๋ฐ๊ฟ์ ๋จ์ด๋ก ๋ณํํ ์ ์๋ ๊ฒฝ์ฐ, ์ด์ ๋
ธ๋๋ก ์ค์ !
let neighbours = getNeighbours(words)
// Step2. begin๋ถํฐ ์์ํ์ฌ ํ ๊ธ์์ฉ ๋ฐ๊ฟ๋๊ฐ๋ฉด์ target์ด ๋๋ ์ต์ ๊ฒฝ๋ก๋ฅผ ์ฐพ๊ธฐ!
return findShortestPath(neighbours, words, target)
}
4. ์ฌํ๊ฒฝ๋ก (DFS)
- tickets ๋ฐฐ์ด์ ํฐ์ผ์ ๋์ฐฉ์ง์ ๋ฐ๋ผ ์ค๋ฆ์ฐจ์ ์ ๋ ฌํ๋ค. * ๊ฒฝ๋ก๊ฐ 2๊ฐ์ง ์ด์์ผ ๋ ์ํ๋ฒณ ์์๊ฐ ์์๋ ๊ฒฝ๋ก๋ฅผ return
- ํฐ์ผ์ ์ฌ์ฉํ๋์ง์ ๋ํด visited ๋ฐฐ์ด๋ก ์ฒดํฌํ๋ค. * ์ฃผ์ด์ง ํญ๊ณต๊ถ์ ๋ชจ๋ ์ฌ์ฉํด์ผํ๋ค.
- ํฐ์ผ์ ๋ํด DFS ์ํ -> ๊ฐ๋ฅํ ๊ฒฝ๋ก๋ฅผ ๋ฐํํ๋ค.
- DFS ์ํ์์, ๋ชจ๋ ํฐ์ผ์ ์์งํด ๊ฒฝ๋ก๋ฅผ ๋ง๋ ๊ฒฝ์ฐ course ๋ฐฐ์ด์ ๋ฐํํ๋ค. ๊ฒฝ๋ก๊ฐ ๋ ์ด์ด์ง์ง ์๋ ๊ฒฝ์ฐ [] ๋ฅผ ๋ฐํ.
- ์ฃผ์์ฌํญ) ๊ฐ์ ๊ฒฝ๋ก์ ํฐ์ผ์ด ์ค๋ณต๋์ด ์ฃผ์ด์ง ์ ์๋ค.
func findCourse(_ tickets: inout [[String]], _ visited: inout [Bool],
_ src: String, _ course: [String]) -> [String] {
if course.count == tickets.count+1 {
return course
}
for (index, ticket) in tickets.enumerated() {
if ticket[0] == src && visited[index] == false {
visited[index] = true
var newCourse = course
newCourse.append(ticket[1]) // add dst
let result = findCourse(&tickets, &visited, ticket[1], newCourse)
if !result.isEmpty { return result }
visited[index] = false
}
}
return []
}
func solution(_ tickets:[[String]]) -> [String] {
// ํฐ์ผ์ ๋์ฐฉ์ง์ ๋ฐ๋ผ ์ค๋ฆ์ฐจ์ ์ ๋ ฌ.
var tickets = tickets.sorted(by: { $0[1] < $1[1] })
// ํฐ์ผ์ ์ฌ์ฉํ๋์ง์ ๋ํด visited ๋ฐฐ์ด๋ก ์ฒดํฌ
var visited = Array(repeating: false, count: tickets.count)
// ํฐ์ผ์ ๋ํด DFS ์ํ -> ๊ฐ๋ฅํ ๊ฒฝ๋ก๋ฅผ ๋ฐํํ๋ค.
return findCourse(&tickets, &visited, "ICN", ["ICN"])
}
์ฌํ๊ฒฝ๋ก ๋ฐ๋ก
* ํ ์คํธ์ผ์ด์ค 1, 2 ๋ฐํ์์๋ฌ์ ๋ํ ๋ฐ๋ก ํฌํจ
// ๋ฐ๋ก 1
print(solution([["ICN", "BBB"],["ICN", "CCC"],["BBB", "CCC"],["CCC", "BBB"],["CCC", "ICN"]]))
// ["ICN", "BBB", "CCC", "ICN", "CCC", "BBB"]
// ๋ฐ๋ก 2
print(solution([["ICN", "SFO"], ["SFO", "ICN"], ["ICN", "SFO"], ["SFO", "QRE"]]))
// ["ICN", "SFO", "ICN", "SFO", "QRE"]
// ๋ฐ๋ก 3
print(solution([["ICN", "BOO"], ["ICN", "COO"], ["COO", "DOO"], ["DOO", "COO"], ["BOO", "DOO"], ["DOO", "BOO"], ["BOO", "ICN"], ["COO", "BOO"]]))
// ["ICN", "BOO", "DOO", "BOO", "ICN", "COO", "DOO", "COO", "BOO"]))
// ๋ฐ๋ก 4 * ๋ฐํ์ ์๋ฌ ํด๊ฒฐ (ZOO ์์ ์ถ๋ฐํ๋ ํฐ์ผ์ด ์์ด ๋์ ๋๋ฆฌ์ ๊ทผx ๋ฐํ์์๋ฌ ๋ฐ์)
print(solution([["ICN", "AOO"], ["AOO", "BOO"], ["AOO", "BOO"], ["BOO", "AOO"], ["BOO", "FOO"], ["FOO", "COO"], ["COO", "ZOO"]]))
// ["ICN", "AOO", "BOO", "AOO", "BOO", "FOO", "COO", "ZOO"]
* DFS / BFS ๋น๊ต
๊ฐ์ด ์คํฐ๋ํ๋ ํ ์ผ๋ฌ ์ค์ํํธ๋์ด ์ ๋ฆฌํด์ฃผ์ ๋ด์ฉ