swift string advancedBy很慢?

时间:2016-04-19 02:36:44

标签: swift

因此,我正在迅速写一些在线评判。

以下是问题:最长的回文子串

给定字符串S,找到S中最长的回文子字符串。您可以假设S的最大长度为1000,并且存在一个唯一最长的回文子字符串。

所以我使用dp在swift中解决它:

class Solution {
    func longestPalindrome(s: String) -> String {
        var hash = Array(count: s.characters.count, repeatedValue: Array(count: s.characters.count, repeatedValue: false))
        for i in 0 ..< s.characters.count {
            hash[i][i] = true
        }
        var maxStart = 0
        var maxEnd = 0
        var maxCount = 1
        for i in 1.stride(through: s.characters.count - 1, by: 1) {
            for j in 0 ..< s.characters.count - 1 {
                if j + i < s.characters.count {
                    if isValidPalindrome(j, j + i, s, hash) {
                        hash[j][j + i] = true
                        if maxCount < i + 1 {
                            maxCount = i
                            maxStart = j
                            maxEnd = j + i
                        }
                    }
                }
                else {
                    break
                }
            }
        }

        // construct max palindrome string, swift string is so dummy
        var str = ""
        for i in maxStart...maxEnd {
            let index = s.characters.startIndex.advancedBy(i)
            str += String(s.characters[index])
        }
        return str
    }

    func isValidPalindrome(start: Int, _ end: Int, _ s: String, _ hash: [[Bool]]) -> Bool {
        // end <= s's length - 1
        let startIndex = s.startIndex.advancedBy(start)
        let endIdnex = s.startIndex.advancedBy(end)
        if end - start == 1 {
            return s[startIndex] == s[endIdnex]
        }
        else {
            let left = start + 1
            let right = end - 1
            return s[startIndex] == s[endIdnex] && hash[left][right]
        }
    }
}

我认为这是正确的,但是当我提交时,总是超出长字符串的时间,如:

"kyyrjtdplseovzwjkykrjwhxquwxsfsorjiumvxjhjmgeueafubtonhlerrgsgohfosqssmizcuqryqomsipovhhodpfyudtusjhonlqabhxfahfcjqxyckycstcqwxvicwkjeuboerkmjshfgiglceycmycadpnvoeaurqatesivajoqdilynbcihnidbizwkuaoegmytopzdmvvoewvhebqzskseeubnretjgnmyjwwgcooytfojeuzcuyhsznbcaiqpwcyusyyywqmmvqzvvceylnuwcbxybhqpvjumzomnabrjgcfaabqmiotlfojnyuolostmtacbwmwlqdfkbfikusuqtupdwdrjwqmuudbcvtpieiwteqbeyfyqejglmxofdjksqmzeugwvuniaxdrunyunnqpbnfbgqemvamaxuhjbyzqmhalrprhnindrkbopwbwsjeqrmyqipnqvjqzpjalqyfvaavyhytetllzupxjwozdfpmjhjlrnitnjgapzrakcqahaqetwllaaiadalmxgvpawqpgecojxfvcgxsbrldktufdrogkogbltcezflyctklpqrjymqzyzmtlssnavzcquytcskcnjzzrytsvawkavzboncxlhqfiofuohehaygxidxsofhmhzygklliovnwqbwwiiyarxtoihvjkdrzqsnmhdtdlpckuayhtfyirnhkrhbrwkdymjrjklonyggqnxhfvtkqxoicakzsxmgczpwhpkzcntkcwhkdkxvfnjbvjjoumczjyvdgkfukfuldolqnauvoyhoheoqvpwoisniv"

我可以在一段时间后得到正确的结果qahaq,我想知道为什么它这么慢。如果我用其他语言写,不是那么糟糕。

我怀疑API s.startIndex.advancedBy(start)正在导致它,但我检查了文档,没有时间复杂性,没有其他方法将int转换为startIndex类型?

任何取代advancedBy的想法?提前谢谢。

2 个答案:

答案 0 :(得分:0)

对于那些有同样问题的人:我将swift String转换为Array,它变得更快。

我还查看了关于advancedBy实现的Swift源代码,这是一个O(n)opreation,这就是为什么它很慢。

对于实施感兴趣的人,请查看https://github.com/apple/swift/blob/8e12008d2b34a605f8766310f53d5668f3d50955/stdlib/public/core/Index.swift

你会看到advancedBy只是多个后继者():

  @warn_unused_result
  public func advanced(by n: Distance) -> Self {
    return self._advanceForward(n)
  }

 /// Do not use this method directly; call advanced(by: n) instead.
  @_transparent
  @warn_unused_result
  internal func _advanceForward(_ n: Distance) -> Self {
    _precondition(n >= 0,
        "Only BidirectionalIndex can be advanced by a negative amount")
    var p = self
    var i : Distance = 0
    while i != n {
      p._successorInPlace()
      i += 1
    }
    return p
  }

答案 1 :(得分:0)

这应该可以解决问题。在实施之前,我建议您查看一些解释,例如这个人。 https://www.youtube.com/watch?v=obBdxeCx_Qs。虽然我相信他的视频有点用处,但我并不隶属于他。

  func longestPalindrome(_ s: String) -> String {
    var charArray = [Character("$"), Character("#")]
    for i in s.characters {
        charArray += [i, Character("#")]
    }
    charArray += [Character("@")]

    var mir = 0, c = 0, r = 0, longestPalindromeIndex = 0, longestPalindromeLength = 0, ss = "", returnString = ""
    var p = [Int]()

    //MARK: For loop
    for i in 0...(charArray.count - 1) {
        p += [0, 0]
        mir = 2 * c - i
        if i < r {
            p[i] = min(r - i, p[mir])
        }

        if i - (1 + p[i]) >= 0 && i + (1 + p[i]) < charArray.count - 1 {
            while charArray[i + (1 + p[i])] == charArray[i - (1 + p[i])] {
                p[i] += 1
            }
        }

        if p[i] > longestPalindromeLength {
            longestPalindromeIndex = i
            longestPalindromeLength = p[i]
        }

        if i + p[i] > r {
            c = i
            r = i + p[i]
        }
    }//for loop


    for i in Array(charArray[(longestPalindromeIndex - longestPalindromeLength)...(longestPalindromeIndex + longestPalindromeLength)]) {
        ss = String(i)
        if ss != "#" && ss != "$" && ss != "@" {
            returnString += ss
        }
    }
    return returnString
}//func