Interview Question
Country: United States
The reason it doesnt work aa is Diego's code considers only odd length palindromes (based on his convention of picking a char as a center and branching left and right). For even length palindormes, there is no single center. for eg maam. Center is aa, consider first a as left-center and second a as right-center
Fix to his code would be considering each char not only as center but also as a left-center
Good code, but few comments on style.
there is no need for the final
if (s[left] == s[right]) {
palindromes.push_back(s.substr(left, right - left + 1));
}
after the while loop. the condition can be changed to (left>=0 instead of left!=0) to remove this code.
and we should not return vector or sets from a function. huge copying involved. pass by reference. this is looked for esp in an itnerview wehn writgin c++ code
otherwise good code.
@justhack4fun688 and @Anonymous1: Thanks for pointing that out. I fixed the code and it should work now.
@Anonymous2: The condition of the while loop cannot be changed to left >= 0 simply because left is of type size_t. This is an unsigned type and left >= 0 will always evaluate to true. Yes, we should return vectors or sets by value when it makes sense[1] (like this code). C++03 compilers use RVO and C++11 have even more room for optimization for copy elision.[2]
[1] http://en.wikipedia.org/wiki/Return_value_optimization
[2] http://stackoverflow.com/questions/3350385/how-to-return-an-object-in-c
@justhack4fun688 You are correct. I fixed the code. It's simpler and worked with everything I tried. Can you please check again?
@justhack4fun688 O(n^2) time worst case. I've heard it's possible to have O(n) but it's a bit more complicated and you have to use Manacher’s Algorithm.
@justhack4fun688 I just did some performance improvements by skipping indexes of already found palindromes. It much faster on the average case, but it's still O(n^2) worst case.
@Diego Giagio the code is better undoubtdly. but last problem is space.How much is its space complexity.? analyse it
@justhack4fun688 The worst case for space is a string with repeated chars, like 'aaaaaaaaa'. Which gives 'a', 'aa', 'aaa', 'aaaa', etc. The formula to calculate the worst case is (n * (n+1))/2 where n is the length of the input string. For a string with 9 repeated 'a's it gives (9 * 10) / 2 = 45. So I would say the worst case space is O(n*(n+1)/2).
@Diego Giagio YA. i know it..its O(n^2). Now for a string of length 10^5 it will take huge memory.Dont u think so?
Not answering the question.
An O(n^2) algorithm is a great response in an interview for this question.
When the interviewer asks for a better algorithm, it does not mean you have done bad. They are looking to see how you think, when trying to come up with a better algo, and are now WANTING or EXPECTING a better algorithm.
Here's a Java code that seems to work :
import java.util.ArrayList;
public class PalindromeFinder {
public static void main (String[] args) {
PalindromeFinder pf = new PalindromeFinder();
System.out.println(pf.countDistinctPalindromes("gfdfhweufuefk"));
}
public int countDistinctPalindromes(String s) {
for (int i = 0; i < s.length(); ++i) {
findPalindromes(s, i);
}
return found.size();
}
private void findPalindromes(String s, int i) {
int j = i,k = i;
while ((j >= 0) && (k < s.length()) && (s.charAt(j) == s.charAt(k))) {
report(s.substring(j--, ++k));
}
if (i == 0) {
return;
}
k = i;
j = i-1;
while ((j >= 0) && (k < s.length()) && (s.charAt(j) == s.charAt(k))) {
report(s.substring(j--, ++k));
}
}
private void report(String s) {
if (!wasFound(s)) {
found.add(s);
// System.out.println(s);
}
}
private boolean wasFound(String s) {
return found.contains(s);
}
private ArrayList<String> found = new ArrayList<String>();
}
The printing of all palindromes was commented out, but you can comment it in again.
Its compexity is actually
p^2
where
p
is the number of (not necessarily unique) palindromes in the given string, S, which itself can be
p = O(n^2)
where
n
is the length of S. (worst case achieved when s consist of just one letter, repeating itself), but it's only because I used Java-supplied List, instead of a ballanced tree or even a Trie to keep track of the already found palindromes. This would improve the running time to
O(p log p) =(worst case) O(n^2 log n)
.
@justhack4fun688
you mean the [p log p] is too slow? I said the p^2 is just because lack of an API for a ballanced tree in java.
I don't think you can do better if you want DISTINCT palindromes..
and actually, it's slightly better than p log p, cause the p inside the log is the number of distinct palindromes, and the p outside is of all of them.
Now that I think of it, the comparison itself is not exactly O(1), but I don't know if it could practically effect the runtime complexity..
do can you describe a sketch of an O(n^2) algorithm? I can't think of a way to do that..
My algorithm iterates the string from left to right once and try to match the palindromes from inside out, adding the matches to a std::unordered_set (hash set). Written in C++.
Output for "civic":
Output for "aba":
Code:
- Diego Giagio December 11, 2013