附加字符串比追加字符快得多

时间:2016-05-27 02:45:18

标签: arrays string swift character

我在黑客等级问题上遇到了https://www.hackerrank.com/challenges/30-review-loop问题,我遇到了一个暂时解决的问题。我希望这里有人可以向我解释为什么一个比另一个快。或者指出解释这种现象的文档

如果您在此处没有帐户,那么您可以在测试用例的数量中提供问题的描述,然后是一个字符串,您的代码将创建一个字符串,其中包含奇数索引中的所有字符和一个包含所有字符的字符串偶数指数中的字符。输入示例

2
Hacker
Rank

返回

Hce akr
Rn ak

简单吧?这是我制作的代码。

if let line = readLine(), numOftests = Int(line) {
    for iter in 0..<numOftests {
        var evenString = ""
        var oddString = ""
        var string = readLine()!
        var arrChars = [Character](string.characters)                           //1
        for idx in 0..<string.characters.count {
            if idx % 2 == 0 {
                oddString.append(arrChars[idx])                                 //1
                //oddString.append(string[string.startIndex.advancedBy(idx)])   //2 <= Times out
            }
            else {
                evenString.append(arrChars[idx])                                //1
                //evenString.append(string[string.startIndex.advancedBy(idx)])  //2 <= Times out
            }
        }
        print("\(oddString) \(evenString)")
    }
}

最初我使用了注释掉的代码。这会导致超时。总结我的问题是使用字符串的下标系统会导致它比索引字符数组慢得多。它让我感到意外,如果它不是黑客级别的讨论组,我就不会找到解决方案。现在它引起了我的兴趣,因为我不知道为什么这会有所作为。

1 个答案:

答案 0 :(得分:2)

问题不在于追加字符串与附加字符的速度。问题是找到要附加的值需要多长时间。

对数组建立索引是O(1),这意味着无论您是访问第一个字符还是第97个字符,它都会在同一时间发生。它是有效的,因为Swift知道数组元素的大小,所以它可以将索引乘以元素的大小来找到第n个元素。

string.startIndex.advancedBy(idx)是O(idx)。这需要更长的时间,具体取决于您进入字符串的距离。访问第97个字符所需的时间大约是访问第一个字符的97倍。为什么?因为Swift中的字符大小不均匀。 Swift字符串完全兼容unicode和&#34;&#34;需要更多的字节来代表&#34; A&#34;。因此,有必要查看从startIndex到您正在访问的每个字符。

那就是说,你没有理由每次都从startIndex开始。如果将当前索引保存在变量中,则每次可以使1前进一次,这将使字符串索引版本与字符数组索引版本的速度大致相同。

var currentIndex = string.startIndex

for idx in 0..<string.characters.count {
    if idx % 2 == 0 {
        oddString.append(string[currentIndex])
    }
    else {
        evenString.append(string[currentIndex])
    }
    currentIndex = currentIndex.successor()
}

那就是说,我可能会这样写:

for (idx, char) in string.characters.enumerate() {
    if idx % 2 == 0 {
        oddString.append(char)
    }
    else {
        evenString.append(char)
    }
}