算法 -- 分割两个字符串得到回文串
- 分割两个字符串得到回文串
提示
中等
114
相关企业
给你两个字符串 a 和 b ,它们长度相同。请你选择一个下标,将两个字符串都在 相同的下标 分割开。由 a 可以得到两个字符串: aprefix 和 asuffix ,满足 a = aprefix + asuffix ,同理,由 b 可以得到两个字符串 bprefix 和 bsuffix ,满足 b = bprefix + bsuffix 。请你判断 aprefix + bsuffix 或者 bprefix + asuffix 能否构成回文串。
当你将一个字符串 s 分割成 sprefix 和 ssuffix 时, ssuffix 或者 sprefix 可以为空。比方说, s = "abc" 那么 "" + "abc" , "a" + "bc" , "ab" + "c" 和 "abc" + "" 都是合法分割。
如果 能构成回文字符串 ,那么请返回 true,否则返回 false 。
注意, x + y 表示连接字符串 x 和 y 。
示例 1:
输入:a = "x", b = "y"
输出:true
解释:如果 a 或者 b 是回文串,那么答案一定为 true ,因为你可以如下分割:
aprefix = "", asuffix = "x"
bprefix = "", bsuffix = "y"
那么 aprefix + bsuffix = "" + "y" = "y" 是回文串。
示例 2:
输入:a = "abdef", b = "fecab"
输出:true
示例 3:
输入:a = "ulacfd", b = "jizalu"
输出:true
解释:在下标为 3 处分割:
aprefix = "ula", asuffix = "cfd"
bprefix = "jiz", bsuffix = "alu"
那么 aprefix + bsuffix = "ula" + "alu" = "ulaalu" 是回文串。
提示:
1 <= a.length, b.length <= 105
a.length == b.length
a 和 b 都只包含小写英文字母
解法:
- 刚开始想的暴力,就是抽取一个判断回文的方法,然后循环拆组字符串判断
class Solution {
public boolean checkPalindromeFormation(String a, String b) {
int n = a.length();
if(checkPalindrome(a)||checkPalindrome(b)){
return true;
}
String apre,asuf,bpre,bsuf;
for(int i =1;i<n;i++){
apre = a.substring(0,i);
asuf = a.substring(i);
bpre = b.substring(0,i);
bsuf = b.substring(i);
apre += bsuf;
bpre += asuf;
if(checkPalindrome(apre) || checkPalindrome(bpre)){
return true;
}
}
return false;
}
private boolean checkPalindrome(String a){
int n = a.length();
if(n == 0)return true;
String a1 = a.substring(0,n/2);
String a2;
if(n%2 == 1){
a2 = a.substring(n/2+1);
}else{
a2 = a.substring(n/2);
}
StringBuilder s2 = new StringBuilder(a2);
a2 = s2.reverse().toString();
if(a1.equals(a2)){
return true;
}else{
return false;
}
}
}
不出所料,超时了 -- (这用例真的sm)
最后执行的输入
添加到测试用例
a =
"dtcwxqkdksglobkkcvcxwisgjfecszsfgcamrmxnplgffgdhpigywnlyexpgqgbdgjssnxrkntivitjpzfzvlqxvgsfcsinbvanrbrrnprtjgsivyqgfgjskdjkhwiznmlmatelxttlasfxtktrfjizdbzpeqdyznnniykjqctcyopnfcyrvvnyazjaymogzlrlzuszsfnbvxxewogoesiupqdtiwfbwcvtogwltbrtxhvkaiejgcrxwlaumcgiiumneodokfeakijoqmijuzywnotfxngroqphxtpdmufjjsmtoihfiamtzvabmtufexmxlejjkcjxubelgqprhxhlizzwqflmjfhoxvsoypahjcowfyguraqivzzvmzvwbtfcgfkbgxxohydsjrfbdshdbhlykdtvhfzjxkwitibuhepyubxzurqrbpmaplpibgwnbhqemtflxlsxjukhokynzktkxfseexcejszdsgmyodkgpovgrafqrtgvwhjxgcbzwofhyfsijwgdwdwjkctwpyczbmqdfsdihrsxadltmvqurxqokmtfwhwljopzqfmijpiqfbqcglsldmbdueifbdebxgkvvcfifrkayvmrwlensmiazffqhohchousnzyehngxzrpzkvrmwiygrqdbrtntpwhicnzdictmwhdzudbantyngydvdwtstpanrdwnsuwshcigmmyoltccxyfwuimyzfyoflrqdermdjktt...
result.viewAll
b =
"oulkdvaesuyzjxtgtttovvehkprxbblksnoofxwylfoljmkoklcztiqtvqshfvzmqcqmusloxjdtayytkyqnjgszjdjrildgsicnrcyynbqezumearjzgblnquhmdxlxyjgjikjznftedqfsubncyzmglkyetstexsaqczxxbohlokjvzbrbkylqwvwmfbmcuqnatqpartphwvvrqjadtbfoduwkgnzanrciejzgiplfxhoyuhjrtpumvnvkpuzzsxdivcpaicbgmmdbryymheczcrfbuneaajpngbobibvktlnoelsumpdtmyjenpadpsgawferkifvbryonlouqzrxxjkoqgkqvstrsdzzvfuwspzadojkmoauvgykspsyoikrkwvijfyghymsdeqslabyvgbcaahdwvtyjlfbitzyppvbqzspoixthzfcxnuettoechbmcwafeenolbfxuwpmujqiniuwltkiszwywapmqwzkcyxfbsiyjmqkukwxbgjzszoxklvphegtfxufwnkgtahtgtbdjjewunoyfenboayeahltczgxzvnqqrjujoaguuepiamnfusepeihncctlrlumigbepjozniqvtgovreflrxbsgnxsjszdwruvdnxjwhfsbjekrbdfevgmgkjgpypkdybewzokuhxesvgkuthvnmkiizmcfwypyqqbmbserplkwtvhnxhgoftyfetnovuhcvtysmryrtmyqfa...
- 所以我不得不看起了题解
题解在判断回文串时,采用了双指针
我没考虑到的简化算法为,若return true,共有四种可能:
(1)a ; (2)b ; (3)apre+bsuf ; (4)bpre+asuf
前两种可能,则为a或b为回文串
第三种可能,若apre长度大于bsuf,则我们将二者长的减短的,得到差值d,
那么apre[0,an-d-1]与bsuf[d,bn-1]为倒序相等,而apre[an-d-1,an-1]自身为回文串,第四种可能同理
故我们设置头尾双指针,依次判断a的头与b的尾是否相等,第一次出现不等时,则分割出判断过的字符串二者倒序相等,现在只需判断中间部分是否回文即可,而中间部分可能来自于a,也可能来自于b,故我们要判断两次
上代码
class Solution {
public boolean checkPalindromeFormation(String a, String b) {
return checkPalindromef(a,b) || checkPalindromef(b,a);
}
public boolean checkPalindromef(String a, String b) {
int left = 0, right = a.length()-1;
while(left<right && a.charAt(left) == b.charAt(right)){
left ++;
right --;
}
if(left>=right){
return true; //说明字符串a与字符串b倒序相等,K=n/2必能组成回文
}
return checkPalindrome(a,left,right) || checkPalindrome(b,left,right);
}
private boolean checkPalindrome(String a,int left,int right){
while(left<right){
if(a.charAt(left) != a.charAt(right)){
return false;
}
left++;
right--;
}
return true;
}
}
看了底下“小懒鼠”的评论之后真是豁然开朗 --
/*
首先,题目里说只有aprefix+bsuffix和bprefix+aprefix,这两种形式合规,而且允许空。
那么合规的就有四种可能:
1. a
2. b
3. aprefix+bsuffix
4. bprefix+asuffix
所以只要将这四种情况都计算一下就可以了。
重点讨论下3,4也是一样的。
假设aprefix.length()>bsuffix.length(), 其中aprefix+bsuffix可以分成[0,l],[l+1,m],[m+1,n]这三段,[m+1,n]就是bsuffix,[0,l]是aprefix的前半部分。
一般的,[0,l] [m+1,n]这两段是要互为回文的,[l+1,m]是要自身回文的。[l+1,m]这一段要么来自于a,要么来自于b,要么为空。
因为都是从两端遍历,所以可以使用双指针。对于3的条件,在[0,l][m+1,n]这两段上要满足a[i]==b[j],
若是不满足这个条件,那对应的应该是在[l+1,m]这一段上,而这一段要满足a[i]==b[j] || b[i]==b[j],否则3的情况不成立。
4同理。
需要判断不成立的条件。
上面四种可能对应的flag:
1. a [-,0,-,-] - 表示该位置可能是0也可能是1
2. b [0,-,-,-]
3. aprefix+bsuffix [0,0,-,0]
4. bprefix+asuffix [0,0,0,-]
*/