给定一个字符串s,分割s使得s的每一个子串都是回文串
返回所有的回文分割结果。(注意:返回结果的顺序需要和输入字符串中的字母顺序一致。)
import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<String>> partition(String s) {
ArrayList<ArrayList<String>> res = new ArrayList<ArrayList<String>>();
if (s == null || s.length() == 0)
return res;
solve(s, 0, new ArrayList<String>(), res);
return res;
}
private void solve(String s, int index, ArrayList<String> preList, ArrayList<ArrayList<String>> res) {
if (index == s.length()) {
res.add(new ArrayList<String>(preList));
return;
}
ArrayList<String> list = new ArrayList<String>(preList);
for (int i = index + 1; i <= s.length(); i++) {
if (isPalindrom(s.substring(index, i))) {
list.add(s.substring(index, i));
solve(s, i, list, res);
list.remove(list.size() - 1);
}
}
}
private boolean isPalindrom(String s) {
if (s == null)
return false;
int l = 0, r = s.length() - 1;
while (l < r) {
if (s.charAt(l++) != s.charAt(r--))
return false;
}
return true;
}
}
import java.util.*;
public class Solution {
public ArrayList<ArrayList<String>> partition(String s) {
ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
ArrayList<String> list = new ArrayList<String>();
if (s == null || s.length() == 0)
return result;
calResult(result,list,s);
return result;
}
/**
* 判断一个字符串是否是回文字符串
*/
private boolean isPalindrome(String str){
int i = 0;
int j = str.length() - 1;
while (i < j){
if (str.charAt(i) != str.charAt(j)){
return false;
}
i++;
j--;
}
return true;
}
/**
* 回溯
* @param result : 最终要的结果集 ArrayList<ArrayList<String>>
* @param list : 当前已经加入的集合 ArrayList<String>
* @param str : 当前要处理的字符串
*/
private void calResult(ArrayList<ArrayList<String>> result
, ArrayList<String> list
, String str)
{
//当处理到传入的字符串长度等于0,则这个集合list满足条件,加入到结果集中
if (str.length() == 0)
result.add(new ArrayList<String>(list));
int len = str.length();
//递归调用
//字符串由前往后,先判断str.substring(0, i)是否是回文字符串
//如果是的话,继续调用函数calResult,把str.substring(i)字符串传入做处理
for (int i=1; i<=len; ++i){
String subStr = str.substring(0, i);
if (isPalindrome(subStr)){
list.add(subStr);
String restSubStr = str.substring(i);
calResult(result,list,restSubStr);
list.remove(list.size()-1);
}
}
}
}
import java.util.*;
public class Solution {
public ArrayList<ArrayList<String>> partition(String s) {
int len=s.length();
ArrayList<ArrayList<String>> list=new ArrayList();
if(len<=0){return null;}
if(len==1){
ArrayList<String> templist=new ArrayList();
templist.add(s);
list.add( templist);
}else{
for(int i=1;i<len+1;i++){
String temp=s.substring(0, i);
if(isPalindrome(temp)){
if(i==len){
ArrayList<String> templist=new ArrayList();
templist.add(temp);
list.add( templist);
}else {
List list1=partition(s.substring(i));
for(int j=0;j<list1.size();j++){
ArrayList<String> templist=new ArrayList();
templist.add(temp);
templist.addAll((Collection) list1.get(j));
list.add( templist);
}
}
}
}
}
return list;
}
boolean isPalindrome(String s){
int len=s.length();
boolean flag=false;
if(len==1){
flag=true;
}else{
int index=len/2;
if(len%2==1){
index=len/2+1;
}
if(s.substring(0,len/2).equals(new StringBuffer(s.substring(index)).reverse().toString())){
flag=true;
}
}
return flag;
}
}
大多数人都用递归,用动态规划方法做了下
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Solution {
public ArrayList < ArrayList<String> > partition(String s) {
ArrayList < ArrayList<String> > result = new ArrayList<>();
ArrayList<String> nullAL = new ArrayList<>();
result.add(nullAL);
int strLength = s.length();
// 遍历s中每个字符
for (int i = 0; i < strLength; i++) {
String palindrome = String.valueOf(s.charAt(i));
ArrayList < ArrayList<String> > additionResult = new ArrayList<>();
for (ArrayList<String> resultAL : result) {
int resultALSize = resultAL.size();
// 如果能和最后一个字符串相等,那么该字符串与最后一个字符串可以构成回文,新建一个list,存储这种情况。
if (resultALSize > 0 && resultAL.get(resultALSize-1).equals(palindrome)) {
ArrayList<String> additionAL = new ArrayList<>(resultAL);
additionAL.set(resultALSize-1, additionAL.get(resultALSize-1)+palindrome);
additionResult.add(additionAL);
}
// 如果能和倒数第二个字符串相等,那么倒数两个字符串与该字符可以构成回文,新建一个list,存储这种情况
if (resultALSize > 1 && resultAL.get(resultALSize-2).equals(palindrome)) {
ArrayList<String> additionAL = new ArrayList<>(resultAL.subList(0, resultALSize-2));
additionAL.add(palindrome+resultAL.get(resultALSize-1)+palindrome);
additionResult.add(additionAL);
}
// 这个字母一定为回文,记录这种情况
resultAL.add(palindrome);
}
result.addAll(additionResult);
}
// 这题坑爹,最后的结果要按每个list中字符串的字典序排列,排列不对不给过
Collections.sort(result, new Comparator<ArrayList < String > >() {
@Override
public int compare(ArrayList<String> o1, ArrayList<String> o2) {
int o1Size = o1.size();
int o2Size = o2.size();
int count = o1Size < o2Size ? o1Size : o2Size;
for (int i = 0; i < count; i++) {
if (o1.get(i).compareTo(o2.get(i)) != 0) {
return o1.get(i).compareTo(o2.get(i));
}
}
return Integer.compare(o1Size, o2Size);
}
});
return result;
}
}
class Solution {
public:
vector<vector<string> > res;
vector<string> temp;
bool isHunwen(string s){
bool flag = true;
int left = 0;
int right = s.size() - 1;
while (left <= right){
if (s[left] != s[right]){
flag = false;
break;
}
left++;
right--;
}
return flag;
}
void dfs(string s, int pos){
if (pos >= s.size()){
res.push_back(temp);
return;
}
for (int i = 1; i <= s.size()-pos; i++){
string sub = s.substr(pos, i);
if (isHunwen(sub)){
temp.push_back(sub);
dfs(s, pos + i);
temp.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
dfs(s, 0);
return res;
}
};
主要思路是回溯:
leetcode 大神代码,还有配图,我就改成了ArrayList
public class myleetcode_139 { ArrayList<ArrayList<String>> resultList; ArrayList<String> current; public ArrayList<ArrayList<String>> partition(String s) { resultList = new ArrayList<ArrayList<String>>(); current = new ArrayList<String>(); findPalindrome(s, 0); return resultList; } /** * 主要思路是回溯 * @param str * @param left */ private void findPalindrome(String str, int left) { //回溯返回条件,left指针已到最后,也就是回溯到底了 if (current.size() > 0 && left >= str.length()) { ArrayList<String> tempList = (ArrayList<String>) current.clone(); resultList.add(tempList); } for (int right = left; right < str.length(); right++) { //不是回文的话,直接right++; if (isPalindrome(str, left, right)) { //添加回文 if (left == right) { current.add(Character.toString(str.charAt(left))); }else{ current.add(str.substring(left, right +1)); } //进行回溯 findPalindrome(str, right + 1); //移除刚刚添加的元素,也就是回到之前的状态,以便走其他分支 current.remove(current.size() - 1); } } } public boolean isPalindrome(String str, int left, int right) { if (left == right) { return true; } while (left < right) { if (str.charAt(left) != str.charAt(right)) { return false; } left++; right--; } return true; } }
import java.util.*;
public class Solution {
public ArrayList<ArrayList<String>> partition(String s) {
ArrayList<ArrayList<String>> res = new ArrayList<>();
help(res,new ArrayList<String>(),s);
return res;
}
private void help(ArrayList<ArrayList<String>> res, ArrayList<String> temp, String s) {
if(s.length() == 0){
res.add(new ArrayList<>(temp));
return;
}
for (int i = 1; i <= s.length(); i++) {
String t = s.substring(0, i);
if(isPalindrome(t)){
temp.add(t);
help(res,temp,s.substring(i));
temp.remove(temp.size()-1);
}
}
}
private boolean isPalindrome(String t) {
return new StringBuilder(t).reverse().toString().equals(t);
}
} import java.util.ArrayList;
/** 分割回文串
*/
public class SplitPalindromeString {
/**
*
* @param s string字符串
* @return string字符串ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<String>> partition (String s) {
// 存放返回的结果数组
ArrayList<ArrayList<String>> result = new ArrayList<>();
// 保存当前正在分割的一个数组集合
ArrayList<String> list = new ArrayList<String>();
findPalindrome(result, list, s);
return result;
}
/**
* 递归实现查找所有的子字符串
* @param result 结果数组
* @param list 当前处理的数组集合
* @param s 当前要处理的字符串
*/
private void findPalindrome(ArrayList<ArrayList<String>> result, ArrayList<String> list, String s) {
if (s == null || s.length() == 0) {
//当前的分割情况下,已经找完了所有的回文字符串
// 注意: 治理不能直接 result.add(list);
result.add(new ArrayList<>(list));
return;
}
// 对字符串 s 从1个到n 分割成字符串,如果是回文的,通过list.add(回文串), 再将进行递归查找后面的回文串,下面是回溯刚才的add 操作
// 因为对于s.substring(0,); 是永远取不到 i 值的,所以这里要注意 i 的下标取值范围
for (int i = 1 ; i <= s.length(); i++) {
String subStr = s.substring(0, i);
if (isPalindrome(subStr)) {
// subStr 是回文串
list.add(subStr);
// 把 s 剩下的部分 作为下一层递归的参数
findPalindrome(result, list, s.substring(i));
// 回溯: 恢复刚才递归前的状态, 即删除当前层次下,最新插入的一个字符串(因为是递归,在递归中插入list的数据必定已经被此语句也删除了相关的一个字符串)
list.remove(list.size() - 1);
}
}
}
/**
* 判断 s 是否是回文串
* @param s
* @return
*/
private boolean isPalindrome (String s) {
for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
SplitPalindromeString splitPalindromeString = new SplitPalindromeString();
String s = "a";
ArrayList<ArrayList<String>> result = splitPalindromeString.partition(s);
}
} import java.util.ArrayList;
public class Solution {
ArrayList<String> list = new ArrayList<>( );
ArrayList<ArrayList<String>> res = new ArrayList<>( );
Boolean[][] p;
public ArrayList<ArrayList<String>> partition(String s) {
p = new Boolean[s.length()][s.length()];
//先把回文串的部分找出来 然后用p存着
for(int i=s.length()-1;i>=0;i--)
{
for(int j=i;j<s.length();j++)
{
if(s.charAt( i )==s.charAt( j ) && (j-i<2 || p[i+1][j-1]))
p[i][j] = true;
else p[i][j]=false;
}
}
//知道了哪段是回文串后直接爆搜吧
dfs( 0,s );
return res;
}
public void dfs(int k,String s)
{
if(k==s.length())
{
ArrayList<String> l = new ArrayList<>( list );
res.add( l );
return;
}
for (int i=k;i<s.length();i++)
{
if(p[k][i])
{
list.add( s.substring( k,i+1 ) );
dfs( i+1,s);
list.remove(list.size()-1);
}
}
}
}
动态规化+搜索==耗时1200多点
这样找回文串是借鉴上一题的大佬的思想,太吊了 //DFS方法
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string> >res;
if(s.size()<=0) return res;
vector<string>temp;
int len=s.size();
for(int i=1;i<=len;++i)
{
string word=s.substr(0,i);//先看str[0-i)是不是回文串
if(!judge(word)) continue;//如果不是返回i+1
temp.push_back(word);//如果是,递归调用返回后半字符串的所有可能回文串
vector<vector<string> >part=partition(s.substr(i));
Combine(res,temp,part);//合并结果
temp.clear();//清除容器
}
return res;
}
private:
bool judge(string str)//判断是否为回文串
{
if(str.size()<=0) return false;
if(str.size()==1) return true;
else{
int front=0;
int later=str.size()-1;
while(later>front)
{
if(str[front]!=str[later])
return false;
--later;
++front;
}
return true;
}
}
void Combine(vector<vector<string> >&res,vector<string>temp,vector<vector<string> >part)
{
if(part.size()<=0) res.push_back(temp);
vector<string>storage;
for(int i=0;i<part.size();++i)
{
storage=temp;
for(int j=0;j<part[i].size();++j)
storage.push_back(part[i][j]);
res.push_back(storage);
}
return ;
}
};
import java.util.ArrayList;
public class Solution {
ArrayList<ArrayList<String>> resultList=new ArrayList<ArrayList<String>>();
ArrayList<String> temp=new ArrayList<>();
public ArrayList<ArrayList<String>> partition(String s) {
findPalindrome(s,0);
return resultList;
}
private void findPalindrome(String s,int left){
//size大于0防止将空数组也置入
if(temp.size()>0&&left>=s.length()){
//add方法是放入引用对象所以要先clone对象在放入
ArrayList<String> tempList = (ArrayList<String>) temp.clone();
resultList.add(tempList);
}
for(int right=left;right<s.length();right++){
String stemp=s.substring(left,right+1);
if(isPalindrome(stemp)){
temp.add(stemp);
//回溯的思想
findPalindrome(s,right+1);
//回溯到原来状态要移除上一步走的路径
temp.remove(temp.size()-1);
}
}
}
private boolean isPalindrome(String s){
if(s.length()==1){return true;}
if(s.substring(0,s.length()/2).equals(new StringBuffer(s.substring((s.length()/2+s.length()%2))).reverse().toString()))
{
return true;
}
return false;
}
}
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string> >result;
vector<string> temp;
if(s.size()==0) return result;
recur(0,0,s,temp,result);
return result;
}
void recur(int i,int j,string s,vector<string> temp,vector<vector<string>>& result){
if(j+1==s.size() && ispalindrome(i,j,s))//最后一个回文
{ temp.push_back(s.substr(i,j-i+1));
result.push_back(temp);
return ;
}
if(j+1==s.size()) return ;
if(ispalindrome(i,j,s))
{
vector<string> copy=temp;
copy.push_back(s.substr(i,j-i+1));
recur(j+1,j+1,s,copy,result);
}
recur(i,j+1,s,temp,result);
}
bool ispalindrome(int i,int j,string s){
while(i<j)
{
if(s[i]!=s[j]) return false;
else
{
i++;
j--;
}
}
return true;
}
};
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string> > result; vector<string> v; DFS(s,v,result); return result;
}
void DFS(string s,vector<string> &v,vector<vector<string> > &result){
if(s.size() < 1){
result.push_back(v);
return; } for(int i=0;i<s.size();i++) { int begin = 0; int end = i; while(begin < end) { if(s[begin] == s[end]) { begin++; end--; }else break; } if(begin >= end) { v.push_back(s.substr(0,i+1)); DFS(s.substr(i+1), v, result); v.pop_back(); } } }
};
vector<vector<string>> partition(string s)
{
str = s;
for (int i = 0; i < (int)s.length(); ++i)
{
for (int j = i; j >= 0; --j)
{
if (is_palindrome(j, i))
{
m_huiwen[i].push_back(j);
}
}
}
for (int i = 0; i < (int)s.length(); ++i)
{
m[i] = solve(i);
}
return m[s.length() - 1];
}
vector<vector<string>> solve(int finish)
{
vector<vector<string>> ans;
if (finish == 0)
{
ans.push_back(vector < string > {str.substr(0, 1)});
return ans;
}
for (auto c : m_huiwen[finish])
{
string s = str.substr(c, finish - c + 1);
if (c == 0)
{
ans.push_back(vector < string > {s});
}
else
{
vector<vector<string>> vec = m[c - 1];
for (auto& c : vec)
{
c.push_back(s);
ans.push_back(c);
}
}
}
sort(ans.begin(),ans.end());
return ans;
}
string str;
};
class Solution {
public:
// backtracking
bool isPalindrome(string &str)
{
int len = str.length();
for(int i=0,j=len-1;i<=j;i++,j--)
if(str[i] != str[j])
return false;
return true;
}
vector<vector<string>> partition(string s)
{
vector<vector<string>> res;
vector<string> combine;
if(s.length() == 0)
return res;
dfs(s,res,combine,0);
return res;
}
void dfs(string &s,vector<vector<string>> &res,vector<string> &combine,int begin)
{
if(begin == s.length())
{
res.push_back(combine);
return;
}
string substring;
for(int i=begin;i<s.length();i++)
{
substring.push_back(s[i]);
if(isPalindrome(substring))
{
combine.push_back(substring);
dfs(s,res,combine,i+1);
combine.pop_back();
}
}
}
};
class Solution {
public:
vector<vector<string>> partition(string s) {
vector<vector<string>> strPalindrome(NULL);
vector<string> strPath(NULL);
PalindromeDFS(s, strPalindrome, strPath);
return strPalindrome;
}
//递归调用保存
void PalindromeDFS(const string &s, vector<vector<string>> &strPalindrome, vector<string> &strPath)
{
int strLength = s.size();
if (strLength < 1)
{
strPalindrome.push_back(strPath);
return;
}
//判断s从0位置开始字符串大小为1,...,s.size()的子串是否是回文,strPath为所有可能字符串的访问路径,只保存回文到strPalindrome
for (int i = 0; i < strLength; i++)
{
int nBegin = 0;
int nTail = i;
if (IsPalindrome(s.substr(0, i+1)))
{
/*Substring(Int32, Int32):从此实例检索子字符串。 子字符串从指定的字符位置开始且具有指定的长度。*/
strPath.push_back(s.substr(0, i+1));
/*Substring(Int32):从此实例检索子字符串。 子字符串在指定的字符位置开始并一直到该字符串的末尾。*/
PalindromeDFS(s.substr(i + 1), strPalindrome, strPath);
strPath.pop_back();
}
}
}
//判断是不是回文
bool IsPalindrome(const string &s)
{
int nBegin = 0;
int nTail = s.size() - 1;
while (nBegin <= nTail)
{
if (s[nBegin] != s[nTail])
{
return false;
}
nBegin++;
nTail--;
}
return true;
}
};
//利用递归的思想
class Solution {
public:
vector<vector<string>> findPal(string s){
int len=s.length();
vector<string> temp;
vector<vector<string>> res1,res2,res;
if(len==1){
temp.push_back(s);
res.push_back(temp);
temp.clear();
return res;
}
res1=findPal(s.substr(1,len-1));
for(int i=0;i<res1.size();i++){
res1[i].push_back(s.substr(0,1));
res.push_back(res1[i]);
}
int pos=s.find(s[0],1);
while(pos!=string::npos){
if(check(s.substr(0,pos+1))){
if(pos==len-1){
temp.push_back(s);
res.push_back(temp);
temp.clear();
break;
}
res2=findPal(s.substr(pos+1,len-pos-1));
for(int i=0;i<res2.size();i++){
res2[i].push_back(s.substr(0,pos+1));
res.push_back(res2[i]);
}
}
pos=s.find(s[0],pos+1);
}
return res;
}
vector<vector<string>> partition(string s) {
vector<vector<string>> res(0);
if(s.length()==0){
return res;
}
res=findPal(s);
for(int i=0;i<res.size();i++){
reverse(res[i].begin(),res[i].end());
}
return res;
}
bool check(string s){
int end =s.length()-1;
for(int i=0;i<end-i;i++){
if(s[i]!=s[end-i])
return false;
}
return true;
}
};
//动态规划+递归实现
class Solution {
public:
//返回以s[i]开始的子串的所有拆分情况
vector<vector<string> > dfs(size_t start, vector<vector<bool> >& flag, string s)
{
vector<vector<string> > res;
//到达末尾
if (start == s.length())
{
vector<string> tmp;
res.push_back(tmp);
}
else
{
//分两部分
for (size_t i = start; i < s.length(); i++)
{
//前半部分为回文
if (flag[start][i] == true)
{
//递归计算后半部分
vector<vector<string> > tmp = dfs(i + 1, flag, s);
//将返回的结果插入前半部分,放入res中
for (size_t k = 0; k < tmp.size(); k++)
{
tmp[k].insert(tmp[k].begin(), s.substr(start, i - start + 1));
res.push_back(tmp[k]);
}
}
}
}
return res;
}
vector<vector<string>> partition(string s) {
vector<bool> tmp(s.size(), false);
vector<vector<bool> > flag(s.size(), tmp);
vector<vector<string> > res;
//flag[i][j]为s[i..j]是否为回文串的标志,用动态规划
//flag[i][j] = true (当s[i]==s[j] 且 flag[i+1][j-1]为true)
for (int i = s.size() - 1; i >= 0; i--)
{
for (size_t j = i; j < s.size(); j++)
{
if (i == j)
{
flag[i][j] = true;
}
else
{
if (s[i] == s[j])
{
if (i + 1 == j || flag[i + 1][j - 1] == true)
flag[i][j] = true;
}
}
}
}
//递归找出拆分方法
res = dfs(0, flag, s);
return res;
}
};