【LeetCode 每日一题】1616. 分割两个字符串得到回文串(medium)

1616. 分割两个字符串得到回文串


a a a b b b 两个字符串在同一位置切割,各自的头与对方的尾相连形成两个新的字符串,若这两个字符串里有一个回文串,则返回真,否则返回假。

模拟 O ( n 2 ) O(n^2) O(n2) 超时

最容易想到的就是模拟,遍历每个位置,把字符串切割、组装、判断是否回文。但是枚举每个位置要 n n n 的时间,判断回文串要 n / 2 n/2 n/2 的时间。总体就是 O ( n 2 ) O(n^2) O(n2) ,超时是必然。

class Solution {
    
    
public:
    bool checkPalindromeFormation(string a, string b) {
    
    
        int len=a.length();
        
        function<bool(string)> fun=[&](string s){
    
    
            int len=s.length();
            for(int i=0;i<(len/2);i++){
    
    
                if(s[i]!=s[len-1-i])return false;
            }
            return true;
        };

        for(int i=0;i<len;i++){
    
    
            string s1=a.substr(0,i)+b.substr(i);
            string s2=b.substr(0,i)+a.substr(i);
            if(fun(s1)||fun(s2))return true;
        }
        return false;
    }
};



优化AC

我们重新审一下题,这个操作,无非就是两个字符串交换尾巴,判断一下是不是回文。假设 a a a 经过某一位置被裁减后接上 b b b 的尾巴之后构成了一个回文串,那被裁下来的头还可以进一步分成 “自己构成回文” 和 “与 b b b 的尾巴构成回文” 的两个部分。比如

a = " p v h m    u p g q e l t o z f t l m f j j d e " a = "pvhm\;upgqeltozftlmfjjde" a="pvhmupgqeltozftlmfjjde"
b = " y j g p    z b e z s p n n p s z e b z m h v p " b = "yjgp\;zbezspnnpszebzmhvp" b="yjgpzbezspnnpszebzmhvp"
满足条件的回文串由 a a a 的头和 b b b 的尾巴构成,而这个回文串可以分为三个部分:
p v h m    z b e z s p n n p s z e b z    m h v p pvhm\;zbezspnnpszebz\;mhvp pvhmzbezspnnpszebzmhvp

这就使得我们可以用两个指针一次性就判断出 a a a 的头和 b b b 的尾巴能不能构成一个回文串。

我们假设 a a a 在上, b b b 在下。初始时 l e f t = 0 left=0 left=0 r i g h t = n − 1 right=n-1 right=n1 ,如果 a [ l e f t ] = = b [ r i g h t ] a[left]==b[right] a[left]==b[right] ,左指针右移,右指针左移。直到 a [ l e f t ]    ! = b [ r i g h t ] a[left]\;!=b[right] a[left]!=b[right] l e f t > = r i g h t left>=right left>=right

  • a [ l e f t ]    ! = b [ r i g h t ] a[left]\;!=b[right] a[left]!=b[right] 。意味着相同部分结束了。这个就是可能的裁剪位置,我们就指针上移或下移。上移意味着 r i g h t right right 是裁剪位置,我们改而判断是否 a [ l e f t ] = = a [ r i g h t ] a[left]==a[right] a[left]==a[right] ;下移意味着 l e f t left left 是裁剪位置,我们改而判断是否 b [ l e f t ] = = b [ r i g h t ] b[left]==b[right] b[left]==b[right] 。若能直到 l e f t > = r i g h t left>=right left>=right ,则该串是回文串。

  • l e f t > = r i g h t left>=right left>=right ,意味着裁剪位置是正中间

上述只是判断 a a a 的头和 b b b 的尾巴能不能构成回文串。我们交换位置, a a a 在下, b b b 在上,再判断一次 b b b 的头和 a a a 的尾巴能不能构成回文串,二者之一满足则返回 t r u e true true

class Solution {
    
    
public:
    bool checkPalindromeFormation(string a, string b) {
    
    
        int len=a.length();
        
        function<bool(string,string)> fun=[&](string a,string b){
    
    
            int n=a.length();
            int i=0,j=n-1;
            while(a[i]==b[j]&&i<j) i++,j--;//找二者之间的相同部分
            if(i>=j) return true;//裁剪点在中间
            int ii=i,jj=j;
            while(b[i]==b[j]&&i<j) i++,j--;//指针下移
            if(i>=j) return true;//,整个字符串遍历完了,是回文
            while(a[ii]==a[jj]&&ii<jj) ii++,jj--;//指针上移
            if(ii>=jj) return true;
            return false;
        };

        return fun(a,b)||fun(b,a);//两种情况之一满足即可
    }
};





菩萨蛮 【清·纳兰性德】

春云吹散湘帘雨,絮粘蝴蝶飞还住。人在玉楼中,楼高四面风。
柳烟丝一把,暝色笼鸳瓦。休近小阑干,夕阳无限山。

  1. 湘帘:用湘妃竹编制的帘子。
  2. 鸳瓦:即鸳鸯瓦。指瓦之成双成对。
  3. 阑干:即栏杆。

猜你喜欢

转载自blog.csdn.net/qq_44623371/article/details/129632163