zoukankan      html  css  js  c++  java
  • [Swift]LeetCode438. 找到字符串中所有字母异位词 | Find All Anagrams in a String

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址:https://www.cnblogs.com/strengthen/p/10334797.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.

    Strings consists of lowercase English letters only and the length of both strings s and pwill not be larger than 20,100.

    The order of output does not matter.

    Example 1:

    Input:
    s: "cbaebabacd" p: "abc"
    
    Output:
    [0, 6]
    
    Explanation:
    The substring with start index = 0 is "cba", which is an anagram of "abc".
    The substring with start index = 6 is "bac", which is an anagram of "abc". 

    Example 2:

    Input:
    s: "abab" p: "ab"
    
    Output:
    [0, 1, 2]
    
    Explanation:
    The substring with start index = 0 is "ab", which is an anagram of "ab".
    The substring with start index = 1 is "ba", which is an anagram of "ab".
    The substring with start index = 2 is "ab", which is an anagram of "ab".

    给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引。

    字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 20100。

    说明:

    • 字母异位词指字母相同,但排列不同的字符串。
    • 不考虑答案输出的顺序。

    示例 1:

    输入:
    s: "cbaebabacd" p: "abc"
    
    输出:
    [0, 6]
    
    解释:
    起始索引等于 0 的子串是 "cba", 它是 "abc" 的字母异位词。
    起始索引等于 6 的子串是 "bac", 它是 "abc" 的字母异位词。
    

     示例 2:

    输入:
    s: "abab" p: "ab"
    
    输出:
    [0, 1, 2]
    
    解释:
    起始索引等于 0 的子串是 "ab", 它是 "ab" 的字母异位词。
    起始索引等于 1 的子串是 "ba", 它是 "ab" 的字母异位词。
    起始索引等于 2 的子串是 "ab", 它是 "ab" 的字母异位词。

    56ms
     1 class Solution {
     2     func findAnagrams(_ s: String, _ p: String) -> [Int] {
     3         let sCount = s.utf8.count
     4         let pCount = p.utf8.count
     5         guard sCount >= pCount else {
     6             return []
     7         }
     8         var a = 97
     9         var map = [Int](repeating: 0, count: 26)
    10         p.utf8.forEach({
    11             map[Int($0) - a] += 1
    12         })
    13         var sArray = Array(s.utf8)
    14         var left = 0
    15         var right = 0
    16         var count = 0 
    17         var res = [Int]()
    18         
    19         while right < sCount {
    20             let rightIndex = Int(sArray[right]) - a
    21             if map[rightIndex] > 0 {
    22                 map[rightIndex] -= 1
    23                 right += 1
    24                 count += 1
    25             } else {
    26                 let leftIndex = Int(sArray[left]) - a
    27                 map[leftIndex] += 1
    28                 left += 1
    29                 count -= 1
    30             }
    31             if count == pCount {
    32                 res.append(left)
    33             }
    34         }
    35         return res
    36     }
    37 }

    80ms

     1 class Solution {
     2     func findAnagrams(_ s: String, _ p: String) -> [Int] {
     3         let s = s.map { letterIndex($0) }
     4         let p = p.map { letterIndex($0) }
     5         
     6         var ref = Array(repeating: 0, count: 26)
     7         for char in p {
     8             ref[char] += 1
     9         }
    10         
    11         var result = [Int]()
    12         var map = ref.map { _ in 0 }
    13         for i in 0..<s.count {
    14             map[s[i]] += 1
    15             if i - p.count >= 0 {
    16                 map[s[i-p.count]] -= 1
    17             }
    18 
    19             if map == ref {
    20                 result.append(i - p.count + 1)
    21             }
    22         }
    23         
    24         return result
    25     }
    26     
    27     func letterIndex(_ letter: Character) -> Int {
    28         return Int(letter.unicodeScalars.first!.value) - Int(Unicode.Scalar("a").value)
    29     }
    30 }

    84ms

     1 class Solution {
     2     func findAnagrams(_ s: String, _ p: String) -> [Int] {
     3         if s.isEmpty {
     4             return []
     5         }
     6         var hash = Array(repeating: 0, count: 256)
     7         for letter in p {
     8             hash[letter.ascii] += 1
     9         }
    10         let s = [Character](s), p = [Character](p)
    11         var left = 0, right = 0, count = p.count
    12         var result = [Int]()
    13         
    14         while right < s.count {
    15             let index = s[right].ascii
    16             if hash[index] >= 1 {
    17                 count -= 1
    18             }
    19             hash[index] -= 1
    20             right += 1
    21             
    22             if count == 0 {
    23                 result.append(left)
    24             }
    25             
    26             if right - left == p.count {
    27                 let leftIndex = s[left].ascii
    28                 if hash[leftIndex] >= 0 {
    29                     count += 1
    30                 }
    31                 hash[leftIndex] += 1
    32                 left += 1
    33             }
    34         }
    35         return result
    36     }
    37 }
    38 
    39 fileprivate extension Character {
    40     var ascii: Int {
    41         let utf8 = String(self).utf8
    42         return Int(utf8[utf8.startIndex])
    43     }
    44 }

    100ms

     1 class Solution {
     2     func findAnagrams(_ s: String, _ p: String) -> [Int] {
     3         if s.count < p.count {
     4             return []
     5         }
     6 
     7         var s = Array(s)
     8         var i = 0, j = p.count - 1
     9 
    10         var pOcc = Array(repeating: 0, count: 26)
    11         var sOcc = Array(repeating: 0, count: 26)
    12 
    13         for char in p {
    14             pOcc[char.asciiValue - 97] += 1
    15         }
    16 
    17         for char in s.prefix(p.count) {
    18             sOcc[char.asciiValue - 97] += 1
    19         }
    20 
    21         var result = [Int]()
    22         while true {
    23             if isValidAnagram(pOcc, sOcc) {
    24                 result.append(i)
    25             }
    26 
    27             i += 1
    28             j += 1
    29             if j >= s.count { break }
    30 
    31             sOcc[s[i - 1].asciiValue - 97] -= 1
    32             sOcc[s[j].asciiValue - 97] += 1
    33         }
    34 
    35         return result
    36     }
    37 
    38     func isValidAnagram(_ s: [Int], _ p: [Int]) -> Bool {
    39         return s == p
    40     }
    41 }
    42 
    43 extension Character {
    44     var asciiValue: Int {
    45         get {
    46             let s = String(self).unicodeScalars
    47             return Int(s[s.startIndex].value)
    48         }
    49     }
    50 }

    128ms

     1 class Solution {
     2     func findAnagrams(_ s: String, _ p: String) -> [Int] {
     3         guard s.count > 0, s.count >= p.count else {
     4             return []
     5         }
     6         let sarr:[Character] = Array(s)
     7         let parr:[Character] = Array(p)
     8         var count = parr.count
     9         var result = Array<Int>()
    10         var map = Dictionary<Character, Int>()
    11         
    12         for p in parr {
    13             if map[p] == nil {
    14                 map[p] = 0
    15             }
    16             map[p]! += 1
    17         }
    18         
    19         var left = 0
    20         var right = 0
    21         
    22         while right < sarr.count {
    23             if map[sarr[right]] == nil {
    24                 map[sarr[right]] = 0
    25             }
    26             
    27             if map[sarr[right]]! > 0 {
    28                 count -= 1
    29             }
    30             map[sarr[right]]! -= 1
    31             right += 1
    32             
    33             if count == 0 {
    34                 result.append(left)
    35             }
    36             
    37             if right - left == parr.count {
    38                 if map[sarr[left]] == nil {
    39                     map[sarr[left]] = 0
    40                 }
    41                 if map[sarr[left]]! >= 0 {
    42                     count += 1
    43                 }
    44                 map[sarr[left]]! += 1
    45                 left += 1
    46             }            
    47         }        
    48         return result
    49     }    
    50 }

    132ms

     1 class Solution {
     2     
     3     let charToIntMap: [Character: Int] = [
     4         "a": 0,
     5         "b": 1,
     6         "c": 2,
     7         "d": 3,
     8         "e": 4,
     9         "f": 5,
    10         "g": 6,
    11         "h": 7,
    12         "i": 8,
    13         "j": 9,
    14         "k": 10,
    15         "l": 11,
    16         "m": 12,
    17         "n": 13,
    18         "o": 14,
    19         "p": 15,
    20         "q": 16,
    21         "r": 17,
    22         "s": 18,
    23         "t": 19,
    24         "u": 20,
    25         "v": 21,
    26         "x": 22,
    27         "w": 23,
    28         "y": 24,
    29         "z": 25
    30     ]
    31     
    32     
    33     func findAnagrams(_ s: String, _ p: String) -> [Int] {
    34         guard s.count >= p.count else { return [Int]() }
    35         var i = 0
    36         var j = 0
    37         let sArr = Array(s)
    38         let pArr = Array(p)
    39         
    40         var pInt = Array<Int>(repeating: 0, count: 26)
    41         var ans = [Int]()
    42         
    43         for ch in pArr {
    44             pInt[charToIntMap[ch]!] = pInt[charToIntMap[ch]!] + 1
    45         }
    46         var movingInt = Array<Int>(repeating: 0, count: 26)
    47         while i < sArr.count && j < pArr.count {
    48             let ch = sArr[i]
    49             movingInt[charToIntMap[ch]!] = movingInt[charToIntMap[ch]!] + 1 
    50             i += 1
    51             j += 1
    52         }
    53         if movingInt == pInt {
    54             ans.append(0)
    55         }
    56         while i < sArr.count {
    57             let ch = sArr[i]
    58             let prevCh = sArr[i - j]
    59             movingInt[charToIntMap[ch]!] = movingInt[charToIntMap[ch]!] + 1 
    60             movingInt[charToIntMap[prevCh]!] = movingInt[charToIntMap[prevCh]!] - 1 
    61             if movingInt == pInt {
    62                 ans.append(i - j + 1)
    63             }
    64             i += 1
    65         }
    66         return ans
    67     }
    68 }

    164ms

     1 class Solution {
     2     func findAnagrams(_ s: String, _ p: String) -> [Int] {
     3         guard s.count >= p.count else { return [] }
     4         let sChars = Array(s.characters.map { String($0).uppercased() })
     5         let pChars = Array(p.characters.map { String($0).uppercased() })
     6         var result = [Int]()
     7         var pCount = Array(repeating: 0, count: 26)
     8         var windowCount = Array(repeating: 0, count: 26)
     9         
    10         for i in 0..<pChars.count {
    11             pCount[Int(UnicodeScalar(pChars[i])!.value) - Int(UnicodeScalar("A")!.value)] += 1
    12             windowCount[Int(UnicodeScalar(sChars[i])!.value) - Int(UnicodeScalar("A")!.value)] += 1
    13         }
    14         
    15         for i in pChars.count..<sChars.count {
    16             if compareArrays(pCount, windowCount) { result.append(i - pChars.count) }
    17             
    18             windowCount[Int(UnicodeScalar(sChars[i - pChars.count])!.value) - Int(UnicodeScalar("A")!.value)] -= 1
    19             windowCount[Int(UnicodeScalar(sChars[i])!.value) - Int(UnicodeScalar("A")!.value)] += 1
    20         }
    21         
    22         if compareArrays(pCount, windowCount) { result.append(sChars.count - pChars.count) }
    23         
    24         return result
    25     }
    26     
    27     func compareArrays(_ a: [Int], _ b: [Int]) -> Bool {
    28         guard a.count == b.count else { return false }
    29         for i in 0..<a.count {
    30             if a[i] != b[i] { return false }
    31         }
    32         return true
    33     }
    34 }

    Runtime: 1776 ms
    Memory Usage: 20.5 MB
     1 class Solution {
     2     func findAnagrams(_ s: String, _ p: String) -> [Int] {
     3         if s.isEmpty || p.count > s.count {return []}
     4         var res:[Int] = [Int]()
     5         var m1:[Int] = [Int](repeating:0,count:256)
     6         var m2:[Int] = [Int](repeating:0,count:256)
     7         var arrS = Array(s).map{$0.ascii}
     8         var arrP = Array(p).map{$0.ascii}
     9         for i in 0..<p.count
    10         {
    11             m1[arrS[i]] += 1
    12             m2[arrP[i]] += 1
    13         }
    14         if m1 == m2
    15         {
    16             res.append(0)
    17         }
    18         for i in p.count..<s.count
    19         {
    20             m1[arrS[i]] += 1
    21             m1[arrS[i - p.count]] -= 1
    22             if m1 == m2
    23             {
    24                 res.append(i - p.count + 1)
    25             }
    26         }
    27         return res
    28     }
    29 }
    30 
    31 extension Character  
    32 {  
    33   //属性:ASCII整数值(定义小写为整数值)
    34    var ascii: Int {
    35         get {
    36             let s = String(self).unicodeScalars
    37             return Int(s[s.startIndex].value)
    38         }
    39     }
    40 }
  • 相关阅读:
    今日SGU 5.2
    奇异值分解(SVD)小结
    计蒜客16495 Truefriend(fwt)
    计蒜客16492 building(二分线段树/分块)
    hihocoder 1323 回文字符串(字符串+dp)
    hihocoder 1320 压缩字符串(字符串+dp)
    hdu6121 build a tree(树)
    hdu6103 Kirinriki(trick+字符串)
    hdu6097 Mindis(几何)
    hdu 6057 Kanade's convolution(子集卷积)
  • 原文地址:https://www.cnblogs.com/strengthen/p/10334797.html
Copyright © 2011-2022 走看看