diff --git a/algorithms/palindrome/palindrome_indices.swift b/algorithms/palindrome/palindrome_indices.swift new file mode 100644 index 0000000..06dd880 --- /dev/null +++ b/algorithms/palindrome/palindrome_indices.swift @@ -0,0 +1,32 @@ +// A palindrome is a string that reads the same forwards and backwards. +// +// Examples: "level", "radar", "madam", "A man, a plan, a canal: Panama". + +extension String { + + /// Iteratively comparing characters from the beginning and end of the string. Only include letters and numbers. + /// - Complexity: O(n), without allocating new space. + func isPalindrome() -> Bool { + var leftIndex = startIndex + var rightIndex = index(before: endIndex) + + while leftIndex < rightIndex { + guard self[leftIndex].isLetter || self[leftIndex].isNumber else { + leftIndex = index(after: leftIndex) + continue + } + guard self[rightIndex].isLetter || self[rightIndex].isNumber else { + rightIndex = index(before: rightIndex) + continue + } + guard self[leftIndex].lowercased() == self[rightIndex].lowercased() else { + return false + } + + leftIndex = index(after: leftIndex) + rightIndex = index(before: rightIndex) + } + + return true + } +} diff --git a/algorithms/palindrome/palindrome_recursion.swift b/algorithms/palindrome/palindrome_recursion.swift new file mode 100644 index 0000000..1eb8b46 --- /dev/null +++ b/algorithms/palindrome/palindrome_recursion.swift @@ -0,0 +1,44 @@ +// A palindrome is a string that reads the same forwards and backwards. +// +// Examples: "level", "radar", "madam", "A man, a plan, a canal: Panama". + +extension String { + + /// Recursively comparing characters from the beginning and end of the string. Only include letters and numbers. + /// - Complexity: O(n), without allocating new space. + func isPalindrome() -> Bool { + isPalindromeRecursion( + leftIndex: startIndex, + rightIndex: index(before: endIndex) + ) + } + + private func isPalindromeRecursion( + leftIndex: String.Index, + rightIndex: String.Index + ) -> Bool { + guard leftIndex < rightIndex else { + return true + } + guard self[leftIndex].isLetter || self[leftIndex].isNumber else { + return isPalindromeRecursion( + leftIndex: index(after: leftIndex), + rightIndex: rightIndex + ) + } + guard self[rightIndex].isLetter || self[rightIndex].isNumber else { + return isPalindromeRecursion( + leftIndex: leftIndex, + rightIndex: index(before: rightIndex) + ) + } + guard self[leftIndex].lowercased() == self[rightIndex].lowercased() else { + return false + } + + return isPalindromeRecursion( + leftIndex: index(after: leftIndex), + rightIndex: index(before: rightIndex) + ) + } +} diff --git a/algorithms/palindrome/palindrome_reversed.swift b/algorithms/palindrome/palindrome_reversed.swift new file mode 100644 index 0000000..0c5659c --- /dev/null +++ b/algorithms/palindrome/palindrome_reversed.swift @@ -0,0 +1,13 @@ +// A palindrome is a string that reads the same forwards and backwards. +// +// Examples: "level", "radar", "madam", "A man, a plan, a canal: Panama". + +extension String { + + /// Using the `reverse()` method to reverse the string and comparing it with the original. Only include letters and numbers. + /// - Complexity: O(n), with allocating O(n) space. + func isPalindrome() -> Bool { + let input = lowercased().filter { $0.isLetter || $0.isNumber } + return input == String(input.reversed()) + } +}