-
Notifications
You must be signed in to change notification settings - Fork 886
/
WordSquares.swift
65 lines (51 loc) · 1.77 KB
/
WordSquares.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* Question Link: https://leetcode.com/problems/word-squares/
* Primary idea: Classic Depth-first Search, fill out row by row, choose correct word with fixed prefix, only need to care which column is used
*
* Time Complexity: O(n^2), Space Complexity: O(n^2)
*
*/
class WordSquares {
func wordSquares(_ words: [String]) -> [[String]] {
guard let first = words.first else {
return [[String]]()
}
let prefixesToWords = buildMaps(words), rowNum = first.count
var paths = [[String]](), path = [String]()
dfs(&paths, path, prefixesToWords, rowNum, 0)
return paths
}
private func dfs(_ paths: inout [[String]], _ path: [String], _ prefixesToWords: [String: [String]], _ rowNum: Int, _ currentRow: Int) {
if currentRow == rowNum {
paths.append(path)
return
}
var prefix = ""
for i in 0..<currentRow {
prefix.append(Array(path[i])[currentRow])
}
guard let words = prefixesToWords[prefix] else {
return
}
for word in words {
dfs(&paths, path + [word], prefixesToWords, rowNum, currentRow + 1)
}
}
private func buildMaps(_ words: [String]) -> [String: [String]] {
var res = [String: [String]]()
for word in words {
for prefix in prefixes(word) {
res[prefix, default: []].append(word)
}
}
return res
}
private func prefixes(_ word: String) -> [String] {
var res = [""], prefix = ""
for char in word {
prefix.append(char)
res.append(prefix)
}
return res
}
}