Reputation: 1933
I am solving the palindrome partition problem which requires to return all palindrome partitions of a given string (http://oj.leetcode.com/problems/palindrome-partitioning/). I found two solutions to this problem. I am having difficulty to understand why there is a huge difference in the running times of these two approaches:
(Assume bool isPal()
is a given function which tells whether given string is palindrome or not in O(length) time)
1st Solution: (Uses backtracking):
void find(string s, int start, vector<string> &r, vector<vector<string> > &res){
if (start >= s.size()){
res.push_back(r);
}else{
for (int i=start;i<s.size();i++){
if (isPal(s.substr(start, i-start+1))){
r.push_back(s.substr(start,i-start+1));
find(s,i+1,r,res);
r.pop_back();
}
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string> > res;
vector<string> r;
find(s,0,r,res);
return res;
}
2nd Solution:
vector<vector<string> > partition(string s) {
vector<vector<string> > answer;
if(s.size() == 0)
return answer;
// if s is Palindrome, push to answer
if(isPal(s))
answer.push_back(vector<string>(1,s));
if(s.size() == 1)
return answer;
for(int i=1; i<s.size(); ++i) {
string s1 = s.substr(0, i);
string s2 = s.substr(i, s.size()-i);
if(isPal(s1)) {
// get sub_answers of partition(s[i:])
vector<vector<string> > sub_answer = partition(s2);
// add s1 to the begin of sub_answers
for(int j=0; j<sub_answer.size(); ++j) {
sub_answer[j].insert(sub_answer[j].begin(), s1);
answer.push_back(sub_answer[j]);
}
}
}
return answer;
}
Even though both the solutions have the same underlying idea, the 1st solution runs in 108ms, while the 2nd one takes 472ms time. Is this because of theoretical inefficiency (maybe 2nd solution solves a single problem multiple times) or because of inefficient implementation (some C++ concepts)? Please point out the reason for inefficiency of 2nd solution.
Note: Both solutions are correct and give the same result.
Upvotes: 1
Views: 144
Reputation: 672
I assume both implementations returns the same result? Other than that, there are to lines worth commenting:
sub_answer[j].insert(sub_answer[j].begin(), s1);
This forces all the content of sub_answer[j]
to be shifted back to give space to s1
. Better add s1
to the vector before adding the rest.
answer.push_back(sub_answer[j]);
sub_answer[j]
is now copied again. Since you don't need sub_answer[j]
any more, you may use std::move
to swap ownership in stead of copying:
answer.push_back(std::move(sub_answer[j]));
Upvotes: 1