Find First Palindromic String in the Array
EasyPrompt
Given an array of strings words, return the first palindromic string in the array. If there is no such string, return an empty string "".
A string is palindromic if it reads the same forward and backward.
Example 1:
Input: words = ["abc","car","ada","racecar","cool"]
Output: "ada"
Explanation: The first string that is palindromic is "ada".
Note that "racecar" is also palindromic, but it is not the first.Example 2:
Input: words = ["notapalindrome","racecar"]
Output: "racecar"
Explanation: The first and only string that is palindromic is "racecar".Example 3:
Input: words = ["def","ghi"]
Output: ""
Explanation: There are no palindromic strings, so the empty string is returned.
Constraints:
1 <= words.length <= 1001 <= words[i].length <= 100words[i]consists only of lowercase English letters.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach iterates through each string in the input array. For each string, it checks if it's a palindrome by creating a reversed copy of the string and comparing it with the original. The first string that matches its reversed version is returned.
Algorithm
- Iterate through each
wordin thewordsarray. - For each
word, call a helper functionisPalindrome(word). - In
isPalindrome(word): a. Create a newStringBuilderobject from theword. b. Reverse theStringBuilder. c. Convert the reversedStringBuilderback to aString. d. Compare the originalwordwith the reversed string. Returntrueif they are equal,falseotherwise. - If
isPalindrome(word)returnstrue, return the currentword. - If the loop completes without finding any palindromes, return an empty string
"".
Walkthrough
The main idea is to traverse the words array from the beginning. For each word, we create a helper function, isPalindrome, to determine if it's a palindrome. Inside isPalindrome, we use a StringBuilder to create a reversed version of the input string. We then convert the StringBuilder back to a String and compare it with the original string using the .equals() method. If isPalindrome returns true, we have found our first palindromic string, and we can immediately return it. If the loop finishes without finding any palindromes, it means no such string exists in the array, so we return an empty string "".
class Solution { public String firstPalindrome(String[] words) { for (String word : words) { if (isPalindrome(word)) { return word; } } return ""; } private boolean isPalindrome(String s) { String reversed_s = new StringBuilder(s).reverse().toString(); return s.equals(reversed_s); }}Complexity
Time
O(N * K), where N is the number of strings in the `words` array and K is the maximum length of a string in the array. We iterate through N words, and for each word of length K, reversing and comparing takes O(K) time.
Space
O(K), where K is the maximum length of a string. This is because we need to create a new string (or `StringBuilder`) of length K to store the reversed version of the string for comparison.
Trade-offs
Pros
Simple to understand and implement.
Leverages built-in language features for string manipulation, leading to concise code.
Cons
Less efficient in terms of space, as it requires extra memory to store the reversed string.
Can be slightly slower in practice due to the overhead of creating new string objects.
This is a more optimized approach. It also iterates through each string in the array, but the palindrome check is performed more efficiently using a two-pointer technique. This avoids creating a new string, thus saving space.
Algorithm
- Iterate through each
wordin thewordsarray. - For each
word, call a helper functionisPalindrome(word). - In
isPalindrome(word): a. Initialize two pointers:left = 0andright = word.length() - 1. b. Loop whileleft < right. c. Inside the loop, check ifword.charAt(left)is not equal toword.charAt(right). If they are different, returnfalse. d. Incrementleftand decrementright. e. If the loop completes, it means all characters matched, so returntrue. - If
isPalindrome(word)returnstrue, return the currentword. - If the loop completes, return an empty string
"".
Walkthrough
Similar to the first approach, we iterate through the words array. The key difference is in the isPalindrome helper function. This function uses two pointers, left starting at the beginning of the string (index 0) and right starting at the end (index length - 1). The pointers move towards each other. In each step, we compare the characters at the left and right pointers. If at any point the characters do not match, we know it's not a palindrome, and the function returns false. If the pointers cross or meet (left >= right) without finding any mismatches, it means the string is a palindrome, and the function returns true. The main function returns the first word for which isPalindrome returns true. If the loop finishes, it returns an empty string.
class Solution { public String firstPalindrome(String[] words) { for (String word : words) { if (isPalindrome(word)) { return word; } } return ""; } private boolean isPalindrome(String s) { int left = 0; int right = s.length() - 1; while (left < right) { if (s.charAt(left) != s.charAt(right)) { return false; } left++; right--; } return true; }}Complexity
Time
O(N * K), where N is the number of strings and K is the maximum length of a string. We iterate through N words. For each word of length K, the two-pointer check takes O(K/2) which is O(K) time.
Space
O(1). The two-pointer check is done in-place and uses only a constant amount of extra space for the pointers, regardless of the input string's length.
Trade-offs
Pros
Highly efficient in terms of space complexity (O(1)).
Generally faster in practice than the reversal method because it avoids object creation and can terminate early as soon as a mismatch is found.
Cons
The implementation is slightly more manual compared to using a built-in reverse function.
Solutions
Solution
class Solution {public String firstPalindrome(String[] words) { for (var w : words) { boolean ok = true; for (int i = 0, j = w.length() - 1; i < j && ok; ++i, --j) { if (w.charAt(i) != w.charAt(j)) { ok = false; } } if (ok) { return w; } } return ""; }}class Solution {public: string firstPalindrome(vector<string> &words) { for (auto &w : words) { bool ok = true; for (int i = 0, j = w.size() - 1; i < j; ++i, --j) { if (w[i] != w[j]) { ok = false; } } if (ok) { return w; } } return ""; }};class Solution: def firstPalindrome( self, words: List[str]) -> str: return next((w for w in words if w == w[:: - 1]), "")Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.