如何使用递归定义在Swift中检查回文

fun*_*ct7 5 recursion palindrome swift

我喜欢Swift的许多功能,但是使用操纵字符串仍然是一大难题。

func checkPalindrome(word: String) -> Bool {
    print(word)
    if word == "" {
        return true
    } else {
        if word.characters.first == word.characters.last {
            return checkPalindrome(word.substringWithRange(word.startIndex.successor() ..< word.endIndex.predecessor()))
        } else {
            return false
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

每当字符串的长度为奇数时,此代码都会失败。我当然可以这样做,所以该块的第一行是if word.characters.count < 2,但是Swift中有没有一种方法可以轻松获取子字符串并进行检查?

更新 我喜欢很多建议,但是我想原来的问题可能会误导人,因为这是关于String的问题,而不是为函数获取正确的结果。

例如,在Python中,checkPalindrome(word [1:-1])适用于递归定义,而Swift代码则不太优雅,因为它需要其他技巧。

小智 9

return word == String(word.reversed())
Run Code Online (Sandbox Code Playgroud)


小智 5

func isPalindrome(myString:String) -> Bool {
    let reverseString = String(myString.characters.reversed())
    if(myString != "" && myString == reverseString) {
        return true
    } else {
        return false
    }
}

print(isPalindrome("madam"))
Run Code Online (Sandbox Code Playgroud)

  • @RostyslavDruzhchenko,您只需将“String(myString.characters.reversed())”替换为“myString.reversed()”即可。 (4认同)

Leo*_*bus 2

extension StringProtocol where Self: RangeReplaceableCollection {
    var letters: Self { filter(\.isLetter) }
    var isPalindrome: Bool {
        let letters = self.letters
        return String(letters.reversed()).caseInsensitiveCompare(letters) == .orderedSame
    }
}
Run Code Online (Sandbox Code Playgroud)
"Dammit I'm Mad".isPalindrome    // true
"Socorram-me subi no onibus em marrocos".isPalindrome   // true
Run Code Online (Sandbox Code Playgroud)

您还可以将字符串分解为字符数组并迭代它们,直到其一半与对应的字符进行一一比较:


func checkPalindrome(_ word: String) -> Bool {
    let chars = Array(word.letters.lowercased())
    for index in 0..<chars.count/2 {
        if chars[index] != chars[chars.count - 1 - index] {
            return false
        }
    }
    return true
}
Run Code Online (Sandbox Code Playgroud)

递归版本修复了无法形成 endIndex < startIndex 范围的问题:


func checkPalindrome<T: StringProtocol>(_ word: T) -> Bool {
    let word = word.lowercased()
        .components(separatedBy: .punctuationCharacters).joined()
        .components(separatedBy: .whitespacesAndNewlines).joined()
    if word == "" || word.count == 1 {
        return true
    } else {
        if word.first == word.last {
            let start = word.index(word.startIndex,offsetBy: 1, limitedBy: word.endIndex) ?? word.startIndex
            let end = word.index(word.endIndex,offsetBy: -1, limitedBy: word.startIndex) ?? word.endIndex
            return checkPalindrome(word[start..<end])
        } else {
            return false
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
checkPalindrome("Dammit I'm Mad")
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,但OP似乎想要一个递归解决方案,也许是一个练习。 (2认同)