[Swift]LeetCode833. 字符串中的查找與替換 | Find And Replace in String

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址: http://www.javashuo.com/article/p-ecvquiqz-me.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

To some string S, we will perform some replacement operations that replace groups of letters with new ones (not necessarily the same size).git

Each replacement operation has 3parameters: a starting index i, a source word x and a target word y.  The rule is that if x starts at position i in the originalstring S, then we will replace that occurrence of x with y.  If not, we do nothing.github

For example, if we have S = "abcd" and we have some replacement operation i = 2, x = "cd", y = "ffff", then because "cd" starts at position 2 in the original string S, we will replace it with "ffff".微信

Using another example on S = "abcd", if we have both the replacement operation i = 0, x = "ab", y = "eee", as well as another replacement operation i = 2, x = "ec", y = "ffff", this second operation does nothing because in the original string S[2] = 'c', which doesn't match x[0] = 'e'.app

All these operations occur simultaneously.  It's guaranteed that there won't be any overlap in replacement: for example, S = "abc", indexes = [0, 1], sources = ["ab","bc"] is not a valid test case.測試

Example 1:ui

Input: S = "abcd", indexes = [0,2], sources = ["a","cd"], targets = ["eee","ffff"]
Output: "eeebffff"
Explanation: "a" starts at index 0 in S, so it's replaced by "eee".
"cd" starts at index 2 in S, so it's replaced by "ffff".

Example 2:this

Input: S = "abcd", indexes = [0,2], sources = ["ab","ec"], targets = ["eee","ffff"]
Output: "eeecd"
Explanation: "ab" starts at index 0 in S, so it's replaced by "eee". 
"ec" doesn't starts at index 2 in the original S, so we do nothing.

Notes:spa

  1. 0 <= indexes.length = sources.length = targets.length <= 100
  2. 0 < indexes[i] < S.length <= 1000
  3. All characters in given inputs are lowercase letters.

對於某些字符串 S,咱們將執行一些替換操做,用新的字母組替換原有的字母組(不必定大小相同)。code

每一個替換操做具備 3 個參數:起始索引 i,源字 x 和目標字 y。規則是若是 x 從原始字符串 S 中的位置 i 開始,那麼咱們將用 y 替換出現的 x。若是沒有,咱們什麼都不作。

舉個例子,若是咱們有 S = 「abcd」 而且咱們有一些替換操做 i = 2,x = 「cd」,y = 「ffff」,那麼由於 「cd」 從原始字符串 S 中的位置 2 開始,咱們將用 「ffff」替換它。

再來看 S = 「abcd」 上的另外一個例子,若是咱們有替換操做 i = 0,x = 「ab」,y = 「eee」,以及另外一個替換操做 i = 2,x = 「ec」,y = 「ffff」,那麼第二個操做將不執行任何操做,由於原始字符串中 S[2] = 'c',與 x[0] = 'e' 不匹配。

全部這些操做同時發生。保證在替換時不會有任何重疊: S = "abc", indexes = [0, 1], sources = ["ab","bc"] 不是有效的測試用例。

示例 1:

輸入:S = "abcd", indexes = [0,2], sources = ["a","cd"], targets = ["eee","ffff"]
輸出:"eeebffff"
解釋:
"a" 從 S 中的索引 0 開始,因此它被替換爲 "eee"。
"cd" 從 S 中的索引 2 開始,因此它被替換爲 "ffff"。

示例 2:

輸入:S = "abcd", indexes = [0,2], sources = ["ab","ec"], targets = ["eee","ffff"]
輸出:"eeecd"
解釋:
"ab" 從 S 中的索引 0 開始,因此它被替換爲 "eee"。
"ec" 沒有從原始的 S 中的索引 2 開始,因此它沒有被替換。 

提示:

  1. 0 <= indexes.length = sources.length = targets.length <= 100
  2. 0 < indexes[i] < S.length <= 1000
  3. 給定輸入中的全部字符都是小寫字母。

36ms

 1 final class Solution {
 2     func findReplaceString(_ S: String, _ indexes: [Int], _ sources: [String], _ targets: [String]) -> String {
 3         var dict: [Int: (String, String)] = Dictionary(uniqueKeysWithValues: zip(indexes, zip(sources, targets)) )
 4         var indexes = indexes.sorted(by: >)
 5         var S = Array(S)
 6         var res = S
 7         for index in indexes {
 8             let val = dict[index]!
 9             let source = Array(val.0)
10             let target = Array(val.1)
11             if hasOccurence(S, source, index) {
12                 res.replaceSubrange(index..<(index &+ source.count), with: target)
13             }
14         }
15         return String(res)
16     }
17     
18     @inline(__always) private func hasOccurence(_ S: [Character], _ source: [Character], _ index: Int) -> Bool {
19         for i in index..<(index + source.count) {
20             if i >= S.count { return false }
21             if S[i] != source[i - index] { return false }
22         }
23         return true
24     }
25 }

40ms

 1 class Solution {    
 2     struct StringReplaceIndex: Comparable {
 3         let index: Int
 4         let source: String
 5         let target: String
 6 
 7         static func < (lhs: StringReplaceIndex, rhs: StringReplaceIndex) -> Bool {
 8             return lhs.index < rhs.index
 9         }
10     }
11 
12     func findReplaceString(_ S: String, _ indices: [Int], _ sources: [String], _ targets: [String]) -> String {
13         // build the replace indices in sorted order
14         var replaceIndices = [StringReplaceIndex]()
15         for i in 0..<indices.count {
16             replaceIndices.append(StringReplaceIndex(index: indices[i], source: sources[i], target: targets[i]))
17         }
18         replaceIndices.sort()
19 
20         var result = [String]()
21 
22         // need to handle the substring when the indices doesn't start from 0
23         if replaceIndices[0].index != 0 {
24             let subString = S.subString(from: 0, to: replaceIndices[0].index - 1)
25             result.append(subString)
26         }
27 
28         for i in 0..<replaceIndices.count {
29             let startIndex = replaceIndices[i].index
30             let endIndex = ((i+1) < replaceIndices.count) ? replaceIndices[i+1].index - 1 : S.count - 1
31             var subString = S.subString(from: startIndex, to: endIndex)
32             if subString.hasPrefix(replaceIndices[i].source) {
33                 subString.removeFirst(replaceIndices[i].source.count)
34                 subString = replaceIndices[i].target + subString
35             }
36             result.append(subString)
37         }
38         return result.reduce("", +)
39     }        
40 }
41     
42 extension String {
43 
44     subscript(i: Int) -> Character {
45         get {
46             return self[index(startIndex, offsetBy: i)]
47         }
48     }
49 
50     func subString(from: Int, to: Int) -> String {
51         guard from <= to else {
52             return ""
53         }
54 
55         let startIndex = self.index(self.startIndex, offsetBy: from)
56         let endIndex = self.index(self.startIndex, offsetBy: to)
57         return String(self[startIndex...endIndex])
58     }
59 
60     func subString(from: Int) -> String {
61         let startIndex = self.index(self.startIndex, offsetBy: from)
62         return String(self.suffix(from: startIndex))
63     }
64 
65     func asciiValues() -> [Int] {
66         return Array(self.utf16).map { Int($0) }
67     }
68 
69     mutating func lTrim(_ regex: String = "^\\s+") {
70         if let trailingSpacesRange = self.range(of: regex, options: .regularExpression) {
71             self.replaceSubrange(trailingSpacesRange, with: "")
72         }
73     }
74 
75     mutating func rTrim(_ regex: String = "\\s+$") {
76         if let trailingSpacesRange = self.range(of: regex, options: .regularExpression) {
77             self.replaceSubrange(trailingSpacesRange, with: "")
78         }
79     }
80 
81     func stringByReplacingAt(_ index: Int, with ch: Character) -> String {
82         var chars = Array(self)
83         chars[index] = ch
84         let modifiedString = String(chars)
85         return modifiedString
86     }
87 }

48ms

 1 class Solution {
 2     private struct ConfirmedReplacement {
 3         let start: String.Index
 4         let end: String.Index
 5         let target: String
 6     }
 7     
 8     func findReplaceString(_ S: String, _ indexes: [Int], _ sources: [String], _ targets: [String]) -> String {
 9         var confirmedTargets: [ConfirmedReplacement] = []
10         //1. confirm
11         for i in 0..<indexes.count {
12             let start = S.index(S.startIndex, offsetBy: indexes[i])
13             let source = sources[i]
14             let end = S.index(start, offsetBy: source.count)
15             let target = targets[i]
16             if S[start..<end] != source {
17                 continue
18             }
19             let confirmed = ConfirmedReplacement(start: start, end: end, target: target)
20             confirmedTargets.append(confirmed)
21         }
22         //2. sort confirmed range
23         confirmedTargets = confirmedTargets.sorted(by: { (lhs, rhs) -> Bool in
24             return rhs.start > lhs.start
25         })
26         //3. fill string
27         var strFragments: [String] = []
28         var index = S.startIndex
29         for target in confirmedTargets {
30             strFragments.append(String(S[index..<target.start]))
31             strFragments.append(target.target)
32             index = target.end
33         }
34         strFragments.append(String(S[index..<S.endIndex]))
35         return strFragments.joined()
36     }
37 }

Runtime: 60 ms
Memory Usage: 19.7 MB
 1 class Solution {
 2     func findReplaceString(_ S: String, _ indexes: [Int], _ sources: [String], _ targets: [String]) -> String {
 3         var S = S
 4         var v:[[Int]] = [[Int]]()
 5         for i in 0..<indexes.count
 6         {
 7             v.append([indexes[i], i])
 8         }
 9         v.sort(by:{(a:[Int],b:[Int]) -> Bool in 
10                    if a[0] == b[0]
11                    {
12                        return a[1] >= b[1]
13                    }
14                    else
15                    {
16                        return a[0] > b[0]
17                    }
18                   })
19         for a in v
20         {
21             var i:Int = a.first!
22             var str:String = sources[a[1]]
23             var t:String = targets[a[1]]
24             if S.subString(i, str.count) == str
25             {
26                 S = S.subString(0, i) + t + S.subString(i + str.count)
27             }
28         }
29         return S
30     }
31 }
32 
33 extension String {
34     // 截取字符串:從index到結束處
35     // - Parameter index: 開始索引
36     // - Returns: 子字符串
37     func subString(_ index: Int) -> String {
38         let theIndex = self.index(self.endIndex, offsetBy: index - self.count)
39         return String(self[theIndex..<endIndex])
40     }
41     
42     // 截取字符串:指定索引和字符數
43     // - begin: 開始截取處索引
44     // - count: 截取的字符數量
45     func subString(_ begin:Int,_ count:Int) -> String {
46         let start = self.index(self.startIndex, offsetBy: max(0, begin))
47         let end = self.index(self.startIndex, offsetBy:  min(self.count, begin + count))
48         return String(self[start..<end]) 
49     }
50 }
相關文章
相關標籤/搜索