• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
haipali
博客园    首页    新随笔    联系   管理    订阅  订阅

算法 -- 分割两个字符串得到回文串

  1. 分割两个字符串得到回文串
    提示
    中等
    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 都只包含小写英文字母

解法:

  1. 刚开始想的暴力,就是抽取一个判断回文的方法,然后循环拆组字符串判断
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...
  1. 所以我不得不看起了题解
    题解在判断回文串时,采用了双指针
    我没考虑到的简化算法为,若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,-]
    */
posted @ 2023-03-18 18:09  蓝光水母  阅读(80)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3