Java 中拆分两个字符串以构成回文

2025 年 5 月 13 日 | 阅读 8 分钟

回文在计算机科学和字符串操作问题中至关重要。回文是指正读反读都相同的字符序列。本问题是经典回文检查的扩展,但有一个有趣的转折:不是检查单个字符串,而是给出了两个字符串,必须确定它们是否可以在某个索引处拆分以形成回文。具体来说,我们检查是否可以通过取一个字符串的前缀和另一个字符串的后缀来形成回文。

问题陈述

给定两个长度相同的字符串 A 和 B,确定是否可以在同一索引处拆分这两个字符串,并重新排列它们的片段以形成回文。具体来说,我们检查是否可以通过取一个字符串的前缀和另一个字符串的后缀来形成回文。

任务是实现一个函数来检查是否可以进行这种拆分。

示例 1

输入

A = "abdef"

B = "fecba"

输出:True

解释

在索引 2 处拆分两个字符串,我们取 A 的前缀“ab”和 B 的后缀“cba”,形成“abcba”,这是一个回文。另一个在索引 3 处的拆分产生“fecdef”,这不是回文。由于至少有一个拆分形成了回文,因此输出为 true。

示例 2

输入

A = "abcdef"

B = "fedcba"

输出:True

解释

由于 B 是 A 的反向,从 0 到 6 的任何索引处的拆分都可以形成回文。例如,在索引 3 处拆分,A 的前缀“abc”和 B 的后缀“cba”组合形成“abccba”,这是一个回文。因此,输出为 true。

示例 3

输入

A = "abcd"

B = "efgh"

输出:False

解释

无论我们在哪里拆分 A 和 B,组合的结果都不会形成回文。由于没有有效的拆分满足回文条件,因此输出为 false。

方法 1:使用暴力法

算法

步骤 1:算法首先确定输入字符串 A 和 B 的长度,并将其存储在变量 n 中。定义一个辅助函数,使用两个指针(一个从左开始,一个从右开始)检查给定字符串是否正反读都相同。

步骤 2:函数遍历所有可能的拆分点,从 0 到 n,将每个索引 i 视为潜在的拆分位置。

步骤 3:在每个拆分索引 i 处,生成两个新字符串。第一个字符串由 A 的前缀(从索引 0 到 i)与 B 的后缀(从索引 i 到 n)连接而成。第二个字符串由 B 的前缀(从索引 0 到 i)与 A 的后缀(从索引 i 到 n)连接而成。

步骤 4:使用辅助函数检查新创建的字符串。如果其中任何一个组合形成回文,则函数立即返回 true。

步骤 5:如果循环完成而没有找到任何有效回文,则函数返回 false,表示没有可能的拆分会产生回文。

步骤 6:使用多个输入用例测试该函数,并打印结果以验证其正确性。

实施

输出

 
Example 1: true
Example 2: true
Example 3: false   

复杂度分析

时间复杂度

此方法的 time complexity 为 O(n²),因为它遍历 n 个拆分点,以 O(n) 时间生成子字符串,并在每次迭代中以 O(n) 时间执行回文检查。

空间复杂度

space complexity 为 O(n),因为在每个拆分点都会创建临时子字符串,但除了输入字符串和临时变量之外,没有使用额外的数据结构。

方法 2:使用递归

算法

步骤 1:算法开始定义一个辅助函数,该函数检查给定字符串是否为回文。该函数通过比较字符串的第一个和最后一个字符来使用递归。如果它们匹配,则函数继续检查下一个内部对,直到找到不匹配或成功匹配所有字符。

步骤 2:实现一个递归函数来检查给定的两个字符串的任何有效拆分是否可以形成回文。它首先比较两个字符串相对两端的字符。如果它们匹配,则函数通过递归调用自身来处理下一组字符,向内移动。

步骤 3:如果不匹配字符,则函数停止递归并返回 false,表示此拆分无法形成回文。如果函数在没有遇到不匹配的情况下到达字符串的中间,则通过确认形成回文来返回 true。

步骤 4:一个包装函数调用递归函数来执行两种可能的拆分:A 的前缀 + B 的后缀,以及 B 的前缀 + A 的后缀。如果其中任何一种形成回文,则返回 true。

步骤 5:使用不同的用例测试该函数以验证正确性。

步骤 6:递归有效地减小问题规模,直到找到回文或检查完所有可能性。

实施

输出

 
Example 1: true
Example 2: true
Example 3: false   

复杂度分析

时间复杂度

此递归方法的 time complexity 为 O(n),因为在最坏的情况下,函数在向内移动时最多比较每个字符一次,从而产生线性数量的递归调用。由于每次调用都执行常量时间的工作,因此总体 time complexity 保持线性。

空间复杂度

space complexity 为 O(n),因为递归函数调用存储在调用栈中。在最坏的情况下,当没有提前终止时,递归深度达到 n,导致 O(n) 的辅助空间使用。

方法 3:前缀-后缀匹配

算法

步骤 1:初始化两个指针,左指针位于给定字符串的索引 0 处,右指针位于索引 n - 1 处。

步骤 2:只要 A[left] 和 B[right] 的字符匹配,就向前移动左指针并向后移动右指针。当找到不匹配或指针交叉时停止。

步骤 3:如果找到不匹配,则检查 A 中剩余的子字符串(从左到右)是否形成回文。如果是,则返回 true。

步骤 4:如果 A 中剩余的子字符串不是回文,则检查 B 中剩余的子字符串(从左到右)是否形成回文。如果是,则返回 true。

步骤 5:交换 A 和 B 的角色,并重复整个过程以验证所有前缀-后缀组合。

步骤 6:如果任何检查证实了有效回文的形成,则返回 true。否则,返回 false。

实施

输出

 
Example 1: true
Example 2: true
Example 3: false   

复杂度分析

时间复杂度

此方法的 time complexity 为 O(N),因为每个字符仅处理一次。

空间复杂度

space complexity 为 O(1),因为只使用了少量额外的变量