回文分区(如何弄清楚如何使用DFS)

时间:2014-12-03 01:18:18

标签: c++ algorithm recursion dynamic depth-first-search

我的一般问题是如何弄清楚如何使用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];
    }
};

3 个答案:

答案 0 :(得分:2)

你到底在问什么?你有正确的工作代码和你的非工作代码没有那么不同。

我想我可以指出您的代码有几个问题 - 可能会对您有所帮助:

    {li>

    palindrome()函数中,您应该将s[i]s[len-1-i]进行比较,而不是s[len-i]中的if,因为在前一种情况下,您将第一个元素(具有索引0)与不存在的元素(索引len)进行比较。这可能是helper()卡住的原因。

    helper()函数flag中的
  1. 未初始化。在for周期中,结束条件应为k<slen-1而不是k<slen,因为在后一种情况下,您将省略检查包含字符串终端符号的子字符串。此外,在i的末尾递增helper()毫无意义。最后,helper()函数中的缩进很麻烦。

  2. 不确定为什么使用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;
 
 }
}