You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过指定字符移动操作将字符串数组转换为回文数组?

判断可通过相邻字符移动转换为回文数组的解法

问题描述

若数组反转后与原数组完全相同,则称该数组为回文数组。
给定一个由字符串组成的数组arr,其中每个arr[i]至少包含两个字符。对于每对相邻元素arr[i]和arr[i+1],你可以执行以下操作之一:

  1. 将arr[i]的最右侧字符移至arr[i+1]的最左侧位置。该操作对任意相邻元素对仅可执行一次。
  2. 将arr[i+1]的最左侧字符移至arr[i]的最右侧位置。该操作对任意相邻元素对同样仅可执行一次。
  3. 不对该相邻元素对执行任何操作。
    请问是否可以通过执行上述操作,将原数组arr转换为回文数组?

示例

输入 arr = ["aa", "bab", "cde", "aba", "ab"],输出为true。操作步骤:

  • 将索引1处元素的首个字符移至索引0处元素的末尾,得到["aab", "ab", "cde", "aba", "ab"];
  • 将索引3处元素的最后一个字符移至索引4处元素的开头,得到["aab", "ab", "cde", "ab", "aab"],该数组为回文数组。

为什么双指针直接解法无效

直接用双指针固定原数组两端对比的思路行不通,因为相邻元素的字符移动会改变两端字符串的形态,原数组的左右端点字符串不一定是最终回文数组的端点形态,必须先枚举端点所有可能的变换后再进行对比。

可行解法思路

核心思路是枚举两端元素的所有可能变换形态,递归验证中间子数组是否能形成回文结构,具体步骤如下:

  1. 对于当前子数组的左端点,生成其所有可能的变换形态(基于与下一个元素的三种操作),同时记录变换后的完整子数组;
  2. 对每个左变换后的子数组,再生成右端点的所有可能变换形态(基于与前一个元素的三种操作);
  3. 检查是否存在某一对变换后的左、右端点字符串相等,若相等则递归处理中间的子数组;
  4. 若任何一条递归路径返回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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 02:57:54