30. 串联所有单词的子串(Swift版)

一、题目

给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例 1:

输入:
  s = "barfoothefoobarman",
  words = ["foo","bar"]
输出:[0,9]

解释:
从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。

示例 2:

输入:
  s = "wordgoodgoodgoodbestword",
  words = ["word","good","best","word"]
输出:[]

二、解题

将字符串(s)分成单词长度(wordLength)种分割方式。
例如示例1:

s="barfoothefoobarman"; words = ["foo","bar"]; wordLength=3;
m1=["foo":1,"bar":1];
组合1:["bar","foo","the","foo","bar","man"]
组合2:["b","arf","oot","hef","oob","arm","an"]
组合3:["ba","rfo","oth","efo","oba","rma","n"]

之后分别处理这三种情况。针对组合的处理见代码实现注释。
时间复杂度为O(m)。n为s的长度,m为words.count。
有两个for循环,第一个for循环为m,第二个for循环为n/m,所以和起来复杂度为O(n)。

三、代码实现

    class Solution {
        func findSubstring(_ s: String, _ words: [String]) -> [Int] {
            if s.isEmpty || words.isEmpty {
                return []
            }
            let wordLength = words[0].count
            var resultARR = [Int]()
            
            
            var m1 = [String: Int]()
            // 将words存入m1中,key为word,value为word在words出现的个数
            for word in words {
                if m1[word] != nil {
                    m1[word]! += 1
                }else {
                    m1[word] = 1
                }
            }
            
            // 遍历wordLength的原因是s的组合方式有wordLength中
            // s="12345678"  wordLength=3
            // 组合一 "123", "456", "78"
            // 组合二 "1", "234", "567", "8"
            // 组合三 "12", "345", "678"
            for i in 0.. m1[t]!) {
                                // 从第left开始往后清理
                                let t1 = subString(s, left, wordLength)
                                m2[t1]! -= 1
                                // 这里的判断是为了区分word重复的情况,当word重复时m2[t1]! == m1[t1]!时,不需要count-1
                                if m2[t1]! < m1[t1]! {
                                    count -= 1
                                }
                                left += wordLength
                            }
                        }
                        // 当count == words.count说明left符合条件,将left添加到最后结果中,并将left向后移动
                        if count == words.count {
                            resultARR.append(left)
                            m2[subString(s, left, wordLength)]! -= 1
                            count -= 1
                            left += wordLength
                        }
                    }else {// 没有找到t,说明匹配中断,需重新处理,并将left向后移动
                        m2.removeAll()
                        count = 0
                        left = j + wordLength
                    }
                }
            }
            return resultARR
        }
        
        func subString(_ s: String, _ loc : Int, _ len : Int) -> String {
            return (s as NSString).substring(with: NSRange(location: loc, length: len))
        }
        
    }

Demo地址:github

你可能感兴趣的:(30. 串联所有单词的子串(Swift版))