1616. 分割两个字符串得到回文串
题目链接:1616. 分割两个字符串得到回文串
方法:模拟 + 双指针
解题思路
- 题目要求,找一个合适的下标
将 分割为 和 ,同样的 分割为 和 ,然后使得 或 为回文字符串,若存在下标 ,则返回true
,否则返回false
。 - 若是
为回文串,则从左→右遍历 ,从右←左遍历 ,判断是否可能存在回文串;同理若是 为回文字符串,则改变遍历方向,从左→右遍历 ,从右←左遍历 ,判断是否可能存在回文串; - 实际上上述的两个过程是相同的,那么可以写成一个函数形式
,在传参数时分别为 和 即对应上述两种过程。 - 如何检查上述情况是否存在?
对于 :初始化 ,从左→右遍历 ,从右←左遍历 ,当 时,检查 或 是否为回文串,若有一个则返回true
,假设是 为回文串,则 构成回文串,此时 。
代码
// 优化后代码
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;
}
};
复杂度分析
时间复杂度:
空间复杂度:
分类:
leetcode题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理