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

题目链接:1616. 分割两个字符串得到回文串

方法:模拟 + 双指针

解题思路

  1. 题目要求,找一个合适的下标 idxa 分割为 a[0,idx]a[idx+1,n1],同样的 b 分割为 b[0,idx]b[idx+1,n1],然后使得 a[0,idx]+b[idx+1,n1]b[0,idx]+a[idx+1,n1] 为回文字符串,若存在下标 idx,则返回 true,否则返回 false
  2. 若是 a[0,idx]+b[idx+1,n1] 为回文串,则从左→右遍历 a,从右←左遍历 b,判断是否可能存在回文串;同理若是 b[0,idx]+a[idx+1,n1]为回文字符串,则改变遍历方向,从左→右遍历 b,从右←左遍历 a,判断是否可能存在回文串;
  3. 实际上上述的两个过程是相同的,那么可以写成一个函数形式 check(),在传参数时分别为 check(a,b)check(b,a) 即对应上述两种过程。
  4. 如何检查上述情况是否存在?
    对于 check(a,b):初始化 l=0,r=n1,从左→右遍历 a,从右←左遍历 b,当 a[l]!=b[r] 时,检查 a[l,r]b[l,r] 是否为回文串,若有一个则返回 true,假设是 a[l,r] 为回文串,则 a[0,l1]+a[l,r]+b[r+1,n1] 构成回文串,此时 idx=r

代码

// 优化后代码
class Solution {
public:
    bool checkPalindrome(string str) {
        int n = str.length();
        for (int i = 0; i < n / 2; i ++ ) {
            if (str[i] != str[n - i - 1]) {
                return false;
            } 
        }
        return true;
    }
    bool check(string a, string b) {
        int n = a.length();
        int l = 0, r = n - 1;
        while (l < r) {
            if (a[l] == b[r]) {
                l ++ ;
                r --;
            } else {
                break;
            }
        }
        if (checkPalindrome(a.substr(l, r - l + 1)) || checkPalindrome(b.substr(l, r - l + 1))) return true;
        return false;
    }
    bool checkPalindromeFormation(string a, string b) {
        // 从左→右遍历a,从右←左遍历b,判断是否可能存在回文串
        // 改变遍历方向,从左→右遍历b,从右←左遍历a,判断是否可能存在回文串
        return check(a, b) || check(b, a);
    }
};
// 优化前代码
class Solution {
public:
    bool checkPalindromeFormation(string a, string b) {
        int n = a.length();
        // a 和 b有一个为回文串,则返回true
        int flag1 = true, flag2 = true;
        for (int i = 0; i <= n / 2; i ++ ) {
            if (a[i] != a[n - i - 1]) {
                flag1 = false;
            } 
            if (b[i] != b[n - i - 1]) {
                flag2 = false;
            } 
        }
        if (flag1 || flag2) return true;
        // 从左→右遍历a,从右←左遍历b,判断是否可能存在回文串
        int l = 0, r = n - 1;
        while (l < r) {
            if (a[l] == b[r]) {
                l ++ ;
                r --;
            } else {
                break;
            }
        }
        if (r == l - 1 || r == l) return true; // 说明左右指针相遇,即可以在此截断,此时a[0, l - 1] + b[l, n - 1]为回文串,此时分开下标为l - 1。
        else if (r - l + 1 != n) { // 否则表明左右指针未相遇,在继续判断a[l, r] 或 b[l, r]是否为回文串,假设a[l, r]为回文串,则a[0, r] + b[r + 1, n - 1]为回文串,此时分开下标为r。
            int left = l, right = r;
            while (left < right) {
                if (a[left] == a[right]) {
                    left ++ ;
                    right -- ;
                } else {
                    break;
                }
            }
            if (left - 1 == right || left == right) return true;
            left = l, right = r;
            while (left < right) {
                if (b[left] == b[right]) {
                    left ++ ;
                    right -- ;
                } else {
                    break;
                }
            }
            if (left - 1 == right || left == right) return true;
        }
        // 同上,改变遍历方向,从左→右遍历b,从右←左遍历a,判断是否可能存在回文串
        l = 0, r = n - 1;
        while (l < r) {
            if (b[l] == a[r]) {
                l ++ ;
                r --;
            } else {
                break;
            }
        }
        if (r == l - 1 || r == l) return true;
        else if (r - l + 1 != n) {
            int left = l, right = r;
            while (left < right) {
                if (a[left] == a[right]) {
                    left ++ ;
                    right -- ;
                } else {
                    break;
                }
            }
            if (left - 1 == right || left == right) return true;
            left = l, right = r;
            while (left < right) {
                if (b[left] == b[right]) {
                    left ++ ;
                    right -- ;
                } else {
                    break;
                }
            }
            if (left - 1 == right || left == right) return true;

        }
        return false;
    }
};

复杂度分析

时间复杂度:O(n)
空间复杂度:O(1)

posted @   lixycc  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示