LeetCode 1616. Split Two Strings to Make Palindrome【字符串,双指针】中等
创始人
2025-05-30 05:50:09
0

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。

为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。

由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。

You are given two strings a and b of the same length. Choose an index and split both strings at the same index, splitting a into two strings: aprefix and asuffix where a = aprefix + asuffix, and splitting b into two strings: bprefix and bsuffix where b = bprefix + bsuffix. Check if aprefix + bsuffix or bprefix + asuffix forms a palindrome.

When you split a string s into sprefix and ssuffix, either ssuffix or sprefix is allowed to be empty. For example, if s = "abc", then "" + "abc""a" + "bc""ab" + "c" , and "abc" + "" are valid splits.

Return true if it is possible to form a palindrome string, otherwise return false.

Notice that x + y denotes the concatenation of strings x and y.

Example 1:

Input: a = "x", b = "y"
Output: true
Explaination: If either a or b are palindromes the answer is true since you can split in the following way:
aprefix = "", asuffix = "x"
bprefix = "", bsuffix = "y"
Then, aprefix + bsuffix = "" + "y" = "y", which is a palindrome.

Example 2:

Input: a = "xbdef", b = "xecab"
Output: false

Example 3:

Input: a = "ulacfd", b = "jizalu"
Output: true
Explaination: Split them at index 3:
aprefix = "ula", asuffix = "cfd"
bprefix = "jiz", bsuffix = "alu"
Then, aprefix + bsuffix = "ula" + "alu" = "ulaalu", which is a palindrome.

Constraints:

  • 1 <= a.length, b.length <= 105
  • a.length == b.length
  • a and b consist of lowercase English letters

题意:两个长度相同的字符串 a 和 b ,选择一个下标,将两个字符串都在 相同的下标 分割开。由 a 可以得到两个字符串: aprefix 和 asuffix ,满足 a = aprefix + asuffix ,同理,由 b 可以得到两个字符串 bprefix 和 bsuffix ,满足 b = bprefix + bsuffix 。判断 aprefix + bsuffix 或者 bprefix + asuffix 能否构成回文串,能则返回 true 。当你将一个字符串 s 分割成 sprefix 和 ssuffix 时, ssuffix 或者 sprefix 可以为空。


解法 贪心+双指针

600
注意,双指针前后缀贪心匹配结束后,两个指针指向的位置恰好就是「接下来要判断的回文串」的左右边界,所以这两块代码逻辑可以无缝对接。

class Solution {
public:bool checkPalindromeFormation(string a, string b) {function isPalindrome = [&](const string &x, int l, int r) {while (l < r && x[l] == x[r]) ++l, --r;return l >= r;};// 双指针判断x的前缀和y的后缀是否组成回文function check = [&](const string &x, const string &y) {for (int i = 0, j = y.size() - 1; i < j; ++i, --j) { // 相向双指针// x从前往后,与y从后往前对比,前后缀尽量匹配// ulac cfd , ula ccfd// zjiz alu , zji zaluif (x[i] != y[j]) { // 字符x[i]和y[j]不等,要组成回文// 可能从i前分割开,于是要看y[i:j]是否回文// 或者从j后分割开,于是要看x[i:j]是否回文return isPalindrome(y, i, j) || isPalindrome(x, i, j);}}return true;};return check(a, b) || check(b, a); }
}; 

解法2 中心扩展+双指针

还可使用中心扩展法(LeetCode 647. Palindromic Substrings)。设 aprefixa_{prefix}aprefix​ 取 aaa 前 mmm 个字符,因此在匹配的回文中也要取 bsuffixb_{suffix}bsuffix​ 的后 mmm 个字符。然后就要看剩下的 aaa 或 bbb 正中心的 n−2mn -2mn−2m 个字符是否是回文串。

回文串分两种:

  • 奇数长度,中间的字母不用管,两侧的各自相等
  • 偶数长度,没有中间的字母,两侧的各自相等

x, y 字符串长度相同,令中心扩展检测回文串函数为 check(x, y, left) ,它从 x[left] 往左扩张、从 y[right] 往右扩展,然后彼此匹配。这里的 left 我们传进去 x.size() / 2 - 1 ,偶数时为左侧的中心、奇数时为中心左边那个位置right = x.size() - left - 1 为与中心对称的位置。

我们调用 check(a, a, left), check(b, b, left) 从中心向两侧分别检测字符串 aaa 和 bbb ,不断扩展,直到字符不相同。然后看 a,ba, ba,b 哪个的中心回文串更长,具体是哪条更长不重要。

再以具有更长中心回文串的那个字符串为标准,将两个字符串前后缀分别拼接,并继续扩展检测,这次检测拼接后的字符串。即调用 check(a, b, left), check(b, a, left) ,这里的 left 是之前遍历结束的位置。

当再次结束检测时,如字符再次不相同,则匹配失败;如全部匹配成功,则 left 应该为-1。

结合下图观看,第一次检测时,字符串 aaa 的中心并没有回文串,而字符串 bbb 有一段合法回文串;第二次检测时,aprefix+bsuffixa_{prefix} + b_{suffix}aprefix​+bsuffix​ 通过测试。最终,aprefixa_{prefix}aprefix​ 、bsuffixb_{suffix}bsuffix​ 和 bbb 的中心子串组合起来,就是拼接后的回文串(所有有底色的字符):

// 中心扩展
class Solution {
public:bool checkPalindromeFormation(string a, string b) {int n = a.size();function check = [&](const string &x, const string& y, int left) {int right = n - left - 1;while (left >= 0 && right < n && x[left] == y[right]) --left, ++right;return left;};int left = n / 2 - 1; // 中心位置left = min(check(a, a, left), check(b, b, left));left = min(check(a, b, left), check(b, a, left));return left == -1;}
}

这种写法与第一种写法相反,是相反双指针

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...