-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path271_Encode_and_Decode_Strings.swift
123 lines (106 loc) · 3.27 KB
/
271_Encode_and_Decode_Strings.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
Done: 21.04.2024. Revisited: N/A
(premium)
Design an algorithm to encode a list of strings to a single string. The encoded string is then decoded back to the original list of strings.
Please implement encode and decode.
Example 1:
Input: ["lint","code","love","you"]
Output:["lint","code","love","you"]
Explanation: One possible encode method is: "leet:;code:;love:;you"
Example 2:
Input: ["we","say",":","yes"]
Output: ["we","say",":","yes"]
Constraints:
0 <= strs.length < 100
0 <= strs[i].length < 200
strs[i] contains only UTF-8 characters.
*/
import Foundation
// Option 1 - incomplete solution with bugs. O(n)
func encodeStr(_ strs: [String]) -> String {
var encodedStr = ""
for str in strs {
encodedStr.append("\(str.count)|\(str)")
}
return encodedStr
}
func decodeStr(_ string: String) -> [String] {
var decoded: [String] = []
var word = ""
var count = ""
var countInt: Int = 0
for (index, ch) in string.enumerated() {
if ch.isNumber {
count.append(ch)
} else if ch == "|" && string[index - 1] == count.last {
countInt = Int(count) ?? 0
} else {
word.append(ch)
countInt -= 1
if countInt == 0 {
decoded.append(word)
word = ""
count = ""
countInt = 0
}
}
}
return decoded
}
extension String {
public subscript(_ idx: Int) -> Character {
self[self.index(self.startIndex, offsetBy: idx)]
}
}
// Option 2 - solution from neetcode. O(n)
func encodeStr2(_ strs: [String]) -> String {
if strs.isEmpty { return "#" }
var counts = [String]()
for str in strs {
counts.append("\(str.count)")
}
return counts.joined(separator: ",") + "#" + strs.joined()
}
func decodeStr2(_ s: String) -> [String] {
if s == "#" { return [] }
let index = s.firstIndex(of: "#")!
let counts = String(s[s.startIndex...s.index(before: index)]).components(separatedBy: ",")
var sIndex = s.index(after: index)
var decodedStrings = [String]()
for count in counts {
let endIndex = s.index(sIndex, offsetBy: Int(count)! - 1)
if sIndex > endIndex {
decodedStrings.append("")
continue
}
decodedStrings.append(String(s[sIndex...endIndex]))
sIndex = s.index(after: endIndex)
}
return decodedStrings
}
// Option 3 - my 2nd take. O(n)
func encodeStr3(_ strs: [String]) -> String {
if strs.isEmpty { return "|" }
var counts = [String]()
for str in strs {
counts.append("\(str.count)")
}
return counts.joined(separator: ",") + "|" + strs.joined()
}
func decodeStr3(_ s: String) -> [String] {
if s == "|" { return [] }
let index = s.firstIndex(of: "|")!
let counts = String(s[s.startIndex...s.index(before: index)]).components(separatedBy: ",")
var sIndex = s.index(after: index)
var decodedStrings = [String]()
for count in counts {
let endIndex = s.index(sIndex, offsetBy: Int(count)! - 1)
if sIndex > endIndex {
decodedStrings.append("")
continue
}
decodedStrings.append(String(s[sIndex...endIndex]))
sIndex = s.index(after: endIndex)
}
return decodedStrings
}