如何从整数数组生成所有可能的回文?
问题分析与解决方案
你的原代码仅能判断整个输入数组是否为回文,无法枚举所有符合要求的回文组合。而全排列的思路存在明显缺陷:会生成大量无效排列,且相同元素的不同选取会导致重复回文输出,时间复杂度极高(O(n! * n)),完全不适合处理稍大的数组。
正确思路
利用回文的结构特性(对称、最多一个元素出现奇数次),通过统计数组中各元素的出现次数来构造所有不重复的回文,步骤如下:
- 统计每个元素的出现次数;
- 分两类构造回文:
- 偶数长度回文:选取至少一对相同元素,每对元素可构成基础偶数回文,若元素出现次数≥4,还可扩展为更长的偶数回文;
- 奇数长度回文:选取一个元素作为中心(出现次数≥1),再选取若干对相同元素放在中心两侧,组合成奇数长度回文;
- 去重并输出所有构造好的回文。
代码实现
#include <iostream> #include <unordered_map> #include <vector> #include <algorithm> using namespace std; // 生成所有偶数长度的回文 void generateEvenPalindromes(unordered_map<int, int>& count, vector<vector<int>>& result) { for (auto& pair : count) { int num = pair.first; int cnt = pair.second; // 至少需要2个相同元素才能组成偶数回文 for (int k = 2; k <= cnt; k += 2) { vector<int> palindrome; // 构建前半部分 for (int i = 0; i < k/2; ++i) { palindrome.push_back(num); } // 镜像生成后半部分 vector<int> temp = palindrome; reverse(temp.begin(), temp.end()); palindrome.insert(palindrome.end(), temp.begin(), temp.end()); result.push_back(palindrome); } } } // 生成所有奇数长度的回文 void generateOddPalindromes(unordered_map<int, int>& count, vector<vector<int>>& result) { // 遍历每个可能的中心元素 for (auto& centerPair : count) { int center = centerPair.first; int centerCnt = centerPair.second; // 中心元素使用次数为奇数 for (int c = 1; c <= centerCnt; c += 2) { vector<int> base; // 中心元素部分 int centerUse = (c + 1)/2; int sideUse = (c - 1)/2; // 构建基础奇数回文(中心+两侧的中心元素) for (int i = 0; i < sideUse; ++i) { base.push_back(center); } base.push_back(center); for (int i = 0; i < sideUse; ++i) { base.push_back(center); } // 仅保留长度≥3的奇数回文(匹配示例需求) if (base.size() >= 3) { result.push_back(base); } // 尝试添加其他成对元素到两侧 for (auto& pair : count) { int num = pair.first; int cnt = pair.second; if (num == center) { // 中心元素剩余可成对使用的次数 int remaining = centerCnt - c; if (remaining < 2) continue; cnt = remaining; } else { if (cnt < 2) continue; } // 最多添加cnt/2对该元素 for (int k = 1; k <= cnt/2; ++k) { vector<int> palindrome = base; // 向前、向后添加k个当前元素 for (int i = 0; i < k; ++i) { palindrome.insert(palindrome.begin(), num); palindrome.push_back(num); } result.push_back(palindrome); } } } } } // 去除重复的回文 void removeDuplicates(vector<vector<int>>& result) { sort(result.begin(), result.end()); auto last = unique(result.begin(), result.end()); result.erase(last, result.end()); } // 格式化输出回文 void printPalindromes(vector<vector<int>>& result) { for (auto& pal : result) { cout << "{ "; for (size_t i = 0; i < pal.size(); ++i) { cout << pal[i]; if (i != pal.size() - 1) { cout << " "; } } cout << " }" << endl; } } int main() { int arr[] = {1, 2, 2, 2, 3}; int n = sizeof(arr)/sizeof(int); unordered_map<int, int> count; for (int i = 0; i < n; ++i) { count[arr[i]]++; } vector<vector<int>> result; generateEvenPalindromes(count, result); generateOddPalindromes(count, result); removeDuplicates(result); printPalindromes(result); return 0; }
代码说明
generateEvenPalindromes:遍历每个元素,根据其出现次数生成所有偶数长度的回文(如两个2、四个2等);generateOddPalindromes:遍历每个元素作为回文中心,生成所有奇数长度的回文(如{2,2,2}、{2,1,2}等);removeDuplicates:通过排序和去重操作,确保输出的回文没有重复;printPalindromes:按照示例中的格式输出所有回文。
运行上述代码,输入{1, 2, 2, 2, 3}时,会输出指定的四个回文:
{ 2 2 } { 2 2 2 } { 2 1 2 } { 2 3 2 }
内容的提问来源于stack exchange,提问作者Mayli
相关产品推荐
相关产品推荐

