【字符串/双指针算法题精讲】分割两个字符串得到回文串(C++/Python双语言版)

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

思路

尽可能多的匹配a的前缀和b的后缀,判断剩下区间内是否有存在回文。否则再重复上述过程,匹配b的前缀和a的后缀。

解题方法

  1. 使用双指针法:对于a的前缀、b的后缀的匹配,左指针从a[0]向右,右指针从b[n-1]向左,尽可能多的(贪心)匹配相等的串。
    请添加图片描述

  2. 结束后,左右指针所夹区间[i:j]分别对a和b串切片、判断回文。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传请添加图片描述

  3. 如果上述不构成回文,再对称判断a的前缀、b的后缀。

  4. 注意,在判断回文串的时候也传入双指针i,j,要考虑奇回文串和偶回文串两种情况。对于奇回文串,i==j是回文成立条件;对于偶回文串,i=j+1是回文成立条件(i到了j的恰好右边一处)。综上可以用i>=j合并。

复杂度

  • 时间复杂度:

O ( n ) O(n) O(n),在第一种a前缀、b后缀匹配时,只需要遍历a-prefix + b-suffix 的长度为n的区间。故为 O ( n ) O(n) O(n)

  • 空间复杂度:

O ( 1 ) O(1) O(1),只需要两个指针i,j

C++(递归法)

//递归法
class Solution {
public:
    bool IsPalindrome(string str,int i,int j) {
        //考虑翻下来的情况
        while (i < j && str[i] == str[j])
                i++, j--;
        return i>=j;
    }
    bool checkPalindromeFormation(string a, string b) {
        //先检索一遍a的前缀与b的后缀的情况
        int m = b.length();
        //双指针法,i先遍历a,j从后遍历b
        int i = 0, j = m - 1;
        while (i < j && a[i] == b[j])
            i++, j--;
        if (IsPalindrome(a, i, j) || IsPalindrome(b, i, j))
            return true;

        //再检索一遍b的前缀和a的后缀的情况
        i = 0, j = m - 1;
        while (i < j && b[i] == a[j])
            i++, j--;
        if (IsPalindrome(a, i, j) || IsPalindrome(b, i, j))
            return true;
        return false;
    }
};

Python

#递归法
class Solution:
    #判断给定字符串str,[i:j+1]是否回文
    def IsPalindrome(self,s:str,i:int,j:int)->bool:
        while i<j and s[i]==s[j]:
            i+=1
            j-=1
        #对于偶回文串——i=j+1;奇回文串 i==j,合并成i>=j
        return i>=j
    def checkPalindromeFormation(self, a: str, b: str) -> bool:
        #尽可能多匹配首尾
        n=len(a)
        i,j=0,n-1
        #考虑a的前缀和b的后缀
        while i<j and a[i]==b[j]:
            i+=1
            j-=1
        if self.IsPalindrome(a,i,j) or self.IsPalindrome(b,i,j):
            return True
        i,j=0,n-1
        #考虑a的后缀和b的前缀
        while i<j and b[i]==a[j]:
            i+=1
            j-=1
        return self.IsPalindrome(a,i,j) or self.IsPalindrome(b,i,j)

C++(迭代)

//迭代法
class Solution {
public:
    bool checkPalindromeFormation(string a, string b) {
        //先检索一遍a的前缀与b的后缀的情况
        int m = b.length();
        //双指针法,i先遍历a,j从后遍历b
        int i = 0, j = m - 1;   
        while (i < j && a[i]==b[j]) 
            i++, j--;

        //考虑翻下来的情况
        int ii = i, jj = j;
        if (b[i] == b[j]) {
            while (i < j && b[i] == b[j])
                i++, j--;
        }
        if (i == j || i - j == 1) return true;

        //考虑翻上去
        i = ii, j = jj;
        if (a[i] == a[j]) {
            while (i < j && a[i] == a[j])
                i++, j--;
        }
        if (i == j || i-j == 1) return true;

        //再检索一遍b的前缀和a的后缀的情况
        i = 0,j=m-1;
        while (i < j && b[i] == a[j])
            i++, j--;
        
        //考虑翻下来的情况x
        ii = i, jj = j;
        if (b[i] == b[j]) {
            while (i < j && b[i] == b[j])
                i++, j--;
        }
        if (i == j || i - j == 1) return true;

        //考虑翻上去
        i = ii, j = jj;
        if (a[i] == a[j]) {
            while (i < j && a[i] == a[j])
                i++, j--;
        }
        if (i == j ||i-j == 1) return true;
        return false;
    }
};
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值