这个题直觉上感觉很简单,但是按照直觉的做法做,却发现corner case不断
看了别人的题解,发现这个题主要考虑这么几种情况:
(首先我们定义一下在i处cut:分割得到[0,i-1],[i,len-1]两个字符串
1.其中一个串本身就是回文串,如aba,abc
那么我们只需要在0处cut(注意,这里i-1<0,代表空串),那么得到空串+aba,以及空串加abc,只要让第一个里的aba和另一个里的空串组合即可得到回文串
因此我们首先检查两个串是否本身就是回文串
2.这里一开始的做法和我的直觉一样:
对a串从前到后遍历,对b串从后到前遍历,这样就是检查a的前缀加上b的后缀的情况,要检查b的前缀加上a的后缀,只需要反过来
但是这样比较的过程中,如果遇到不相同,也就是如果继续遍历就无法构成回文串了,那该如何应对?我的直觉并没有给出解决方案
现在想来:
到了不相等的时候,比如abcedd,cddmba,不相等时,指针分别为i=2,j=3,我们要么在i=2处分割,得到ab,cedd以及cd,dmba,要么在i=4处分割,得到abce,dd与cddm,ba,这样分割再组合(此时都是考虑a的前缀和b的后缀组合)分别可以得到:abdmba和abceba
能否是回文串,只取决于dm或ce
因此,当遍历到不相等,就应该判断两种情况下,中间的字符串是否是回文串
如果是将b的前缀和a的后缀相连,做法也一样
class Solution {
private boolean isPalindrome(String s,int lo,int hi){
while(lo<hi){
if(s.charAt(lo)!=s.charAt(hi)){
return false;
}
lo++;
hi--;
}
return true;
}
private boolean helper(String a,String b){
int lo=0,hi=b.length()-1;
while(lo<hi){
if(a.charAt(lo)!=b.charAt(hi)){
break;
}
lo++;
hi--;
}
if(lo<hi){
// 说明遇到了不相等的,此时需要判断两种情况下得到新串的中间部分是否是回文串
return isPalindrome(b,lo,hi)||isPalindrome(a,lo,hi);
}
// 说明不存在中间串,绝对是回文串
return true;
}
public boolean checkPalindromeFormation(String a, String b) {
int len=a.length();
if(isPalindrome(a,0,len-1)||isPalindrome(b,0,len-1)){
return true;
}
// 这里可以增加判断:(a,b)是a的前缀配b的后缀,那么必须a的首字符等于b的末尾字符才需要进一步判断(helper)
return helper(a,b)||helper(b,a);
}
}