能否通过指定字符移动操作将字符串数组转换为回文数组?
判断可通过相邻字符移动转换为回文数组的解法
问题描述
若数组反转后与原数组完全相同,则称该数组为回文数组。
给定一个由字符串组成的数组arr,其中每个arr[i]至少包含两个字符。对于每对相邻元素arr[i]和arr[i+1],你可以执行以下操作之一:
- 将
arr[i]的最右侧字符移至arr[i+1]的最左侧位置。该操作对任意相邻元素对仅可执行一次。- 将
arr[i+1]的最左侧字符移至arr[i]的最右侧位置。该操作对任意相邻元素对同样仅可执行一次。- 不对该相邻元素对执行任何操作。
请问是否可以通过执行上述操作,将原数组arr转换为回文数组?
示例
输入 arr = ["aa", "bab", "cde", "aba", "ab"],输出为true。操作步骤:
- 将索引1处元素的首个字符移至索引0处元素的末尾,得到
["aab", "ab", "cde", "aba", "ab"]; - 将索引3处元素的最后一个字符移至索引4处元素的开头,得到
["aab", "ab", "cde", "ab", "aab"],该数组为回文数组。
为什么双指针直接解法无效
直接用双指针固定原数组两端对比的思路行不通,因为相邻元素的字符移动会改变两端字符串的形态,原数组的左右端点字符串不一定是最终回文数组的端点形态,必须先枚举端点所有可能的变换后再进行对比。
可行解法思路
核心思路是枚举两端元素的所有可能变换形态,递归验证中间子数组是否能形成回文结构,具体步骤如下:
- 对于当前子数组的左端点,生成其所有可能的变换形态(基于与下一个元素的三种操作),同时记录变换后的完整子数组;
- 对每个左变换后的子数组,再生成右端点的所有可能变换形态(基于与前一个元素的三种操作);
- 检查是否存在某一对变换后的左、右端点字符串相等,若相等则递归处理中间的子数组;
- 若任何一条递归路径返回
true,则整体结果为true;若所有路径都验证失败,则返回false。
边界情况处理
- 当子数组长度≤1时,直接返回
true(单个元素本身就是回文); - 当子数组长度为2时,枚举两个元素的所有操作组合,检查是否能得到两个相等的字符串(长度为2的回文数组要求两个元素相等)。
代码实现(Python)
def can_form_palindrome(arr): def helper(sub_arr): n = len(sub_arr) if n <= 1: return True # 处理长度为2的子数组 if n == 2: a, b = sub_arr[0], sub_arr[1] # 枚举所有可能的操作组合 possible_pairs = [ (a, b), # 不操作 (a[:-1], a[-1] + b), # 移a最后一个字符到b (a + b[0], b[1:]) # 移b第一个字符到a ] for x, y in possible_pairs: if x == y: return True return False # 生成左端点的所有可能变换及对应的子数组 left_options = [] first, second = sub_arr[0], sub_arr[1] # 不操作左相邻对 left_options.append((first, sub_arr)) # 移左端点最后一个字符到下一个元素 new_left = first[:-1] new_second = first[-1] + second left_options.append((new_left, [new_left, new_second] + sub_arr[2:])) # 移下一个元素的第一个字符到左端点 new_left2 = first + second[0] new_second2 = second[1:] left_options.append((new_left2, [new_left2, new_second2] + sub_arr[2:])) # 遍历左端点的所有变换,再处理右端点 for left_str, modified_arr in left_options: right_options = [] last, second_last = modified_arr[-1], modified_arr[-2] # 不操作右相邻对 right_options.append((last, modified_arr)) # 移前一个元素最后一个字符到右端点 new_right = second_last[-1] + last new_second_last = second_last[:-1] right_options.append((new_right, modified_arr[:-2] + [new_second_last, new_right])) # 移右端点第一个字符到前一个元素 new_right2 = last[1:] new_second_last2 = second_last + last[0] right_options.append((new_right2, modified_arr[:-2] + [new_second_last2, new_right2])) # 检查当前左右变换后的字符串是否相等,相等则递归处理中间 for right_str, final_arr in right_options: if left_str == right_str: if helper(final_arr[1:-1]): return True return False return helper(arr) # 测试示例 test_arr = ["aa", "bab", "cde", "aba", "ab"] print(can_form_palindrome(test_arr)) # 输出 True
代码说明
- 递归函数
helper负责处理当前子数组的验证逻辑; - 对长度大于2的子数组,先枚举左端点的所有可能变换,再对每个左变换后的数组枚举右端点的变换;
- 只要找到一组左右变换后的字符串相等,且中间子数组能形成回文,就返回
true。
内容的提问来源于stack exchange,提问作者akhiilgupta
相关产品推荐
相关产品推荐

