我的一般问题是如何弄清楚如何使用DFS。这似乎是我知识的一个薄弱环节。我有一个模糊的想法,但经常在问题发生变化时卡住。这给我带来了很多困惑。
对于这个问题,我对如何使用递归编写DFS感到困惑。
给定字符串s
,分区s
,使得分区的每个子字符串都是回文。
返回s
的所有可能的回文分区。
例如,给定s = "aab"
,
返回
[
["aa","b"],
["a","a","b"]
]
我的第一次尝试陷入了辅助函数的循环中。然后从互联网上搜索,我发现bool palindrome(string s)
可以写成不同的签名。
bool palindrome(string &s, int start, int end)
这导致了正确的解决方案。
这是我最初尝试的代码:
class Solution {
public:
bool palindrome(string s)
{
int len = s.size();
for (int i=0;i<len/2; i++)
{
if (s[i]!=s[len-i])
return false;
}
return true;
}
void helper( int i, string s, vector<string> &p, vector<vector<string>> &ret)
{
int slen = s.size();
if (i==slen-1&&flag)
{
ret.push_back(p);
}
for (int k=i; k<slen; k++)
{
if (palindrome(s.substr(0,k)))
{
p.push_back(s.substr(0,k)); //Got stuck
}
}
i++;
}
vector<vector<string>> partition(string s) {
vector<vector<string>> ret;
int len=s.size();
if (len==0) return ret;
vector<string> p;
helper(0,s,p,ret);
return ret;
}
};
纠正一个:
class Solution {
public:
bool palindrome(string &s, int start, int end)
{
while(start<end)
{
if (s[start]!=s[end])
return false;
start++;
end--;
}
return true;
}
void helper( int start, string &s, vector<string> &p, vector<vector<string>> &ret)
{
int slen = s.size();
if (start==slen)
{
ret.push_back(p);
return;
}
for (int i=start; i<s.size(); i++)
{
if (palindrome(s, start, i))
{
p.push_back(s.substr(start,i-start+1));
helper(i+1,s,p,ret);
p.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string>> ret;
int len=s.size();
if (len==0) return ret;
vector<string> p;
helper(0,s,p,ret);
return ret;
}
};
编辑2014年12月4日:我看到了一些使用动态编程的方法,但无法完全理解代码。
电除尘器。 isPalin[i][j] = (s[i] == s[j]) && ((j - i < 2) || isPalin[i+1][j-1]);
为什么j-I<2
代替j-I<1
?
class Solution {
public:
vector<vector<string>> partition(string s) {
int len = s.size();
vector<vector<string>> subPalins[len+1];
subPalins[0] = vector<vector<string>>();
subPalins[0].push_back(vector<string>());
bool isPalin[len][len];
for (int i=len-1; i>=0; i--)
{
for (int j=i; j<len; j++)
{
isPalin[i][j] = (s[i]==s[j])&&((j-i<2)||isPalin[i+1][j-1]);
}
}
for (int i=1; i<=len;i++)
{
subPalins[i]=vector<vector<string>>();
for (int j=0; j<i; j++)
{
string rightStr=s.substr(j,i-j);
if (isPalin[j][i-1])
{
vector<vector<string>> prepar=subPalins[j];
for (int t=0; t<prepar.size(); t++)
{
prepar[t].push_back(rightStr);
subPalins[i].push_back(prepar[t]);
}
}
}
}
return subPalins[len];
}
};
答案 0 :(得分:2)
你到底在问什么?你有正确的工作代码和你的非工作代码没有那么不同。
我想我可以指出您的代码有几个问题 - 可能会对您有所帮助:
在palindrome()
函数中,您应该将s[i]
与s[len-1-i]
进行比较,而不是s[len-i]
中的if
,因为在前一种情况下,您将第一个元素(具有索引0)与不存在的元素(索引len
)进行比较。这可能是helper()
卡住的原因。
helper()
函数flag
中的未初始化。在for
周期中,结束条件应为k<slen-1
而不是k<slen
,因为在后一种情况下,您将省略检查包含字符串终端符号的子字符串。此外,在i
的末尾递增helper()
毫无意义。最后,helper()
函数中的缩进很麻烦。
不确定为什么使用DFS - 图表的含义是什么,这里的顶点和边是什么?至于递归如何在这里起作用:在helper()
函数中,你开始检查作为回文的长度增加的子串。如果找到了回文,则将其放入p
向量(代表您当前的分区)并尝试通过递归调用helper()
将字符串的其余部分分解为回文。如果你成功了(即如果整个字符串被完全分成了回文),你将p
向量(当前分区)的内容放入ret
(所有找到的分区的集合),然后清除{ {1}}准备分析下一个分区(p
的清除是通过p
的递归调用之后的pop_back()
调用实现的。另一方面,如果你未能将字符串完全打破为回文,那么helper()
也会被清除,但不会将其内容转移到p
(这是因为递归调用了最后一段字符串 - 不是回文 - 返回而不调用ret
作为最终符号,因此不会将helper()
推入p
。因此,您最终会在ret
中进行所有可能的回文分区。
答案 1 :(得分:0)
嗨〜这是我使用DFS +回溯的代码。
class Solution
{
public:
bool isPalindrome (string s) {
int i = 0, j = s.length() - 1;
while(i <= j && s[i] == s[j]) {
i++;
j--;
}
return (j < i);
}
void my_partition(string s, vector<vector<string> > &final_result, vector<string> &every_result ) {
if (s.length() ==0)
final_result.push_back(every_result);
for (int i =1; i <= s.length();++i) {
string left = s.substr(0,i);
string right = s.substr(i);
if (isPalindrome(left)) {
every_result.push_back(left);
my_partition(right, final_result, every_result);
every_result.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string> > final_result;
vector<string> every_result;
my_partition(s, final_result, every_result);
return final_result;
}
};
答案 2 :(得分:0)
我使用回溯进行了Palindrome分区。这里使用了深度优先搜索,想法是拆分给定的字符串,使前缀是回文。在向量中推送前缀现在探索留下该前缀的字符串,然后最后弹出最后插入的元素, 好好花时间回溯是形式,选择元素,探索没有它并且不选择它。
enter code here
#include<iostream>
#include<vector>
#include<string>
using namespace std;
bool ispalidrome(string x ,int start ,int end){
while(end>=start){
if(x[end]!=x[start]){
return false;
}
start++;
end--;
}
return true;
}
void sub_palidrome(string A,int size,int start,vector<string>&small, vector < vector < string > >&big ){
if(start==size){
big.push_back(small);
return;
}
for(int i=start;i<size;i++){
if( ispalidrome(A,start,i) ){
small.push_back(A.substr(start,i-start+1));
sub_palidrome(A,size,i+1,small,big);
small.pop_back();
}
}
}
vector<vector<string> > partition(string A) {
int size=A.length();
int start=0;
vector <string>small;
vector < vector < string > >big;
sub_palidrome(A,size,start,small,big);
return big;
}
int main(){
vector<vector<string> > sol= partition("aab");
for(int i=0;i<sol.size();i++){
for(int j=0;j<sol[i].size();j++){
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
}