
给定等长字符串数组,需构造一个长度相同的回文串,使其与所有输入串的字符绝对距离之和最小;当存在多个最优解时,返回字典序最小者。核心在于:回文串第 i 位与第 m−1−i 位必须相同,而该最优字符应取所有字符串在位置 i 和对称位置上的字符的加权中位数。
给定等长字符串数组,需构造一个长度相同的回文串,使其与所有输入串的字符绝对距离之和最小;当存在多个最优解时,返回字典序最小者。核心在于:回文串第 i 位与第 m−1−i 位必须相同,而该最优字符应取所有字符串在位置 i 和对称位置上的字符的加权中位数。
要解决「构造最小误差回文串」问题,关键在于理解误差函数的可分离性与回文约束的耦合关系。
误差可分离性:总误差 = Σi=0m−1 Σk=0n−1 |sk[i] − α[i]|。由于绝对值函数是凸函数,且各位置相互独立,因此每个位置 i 的最优字符选择互不影响——但注意:回文约束强制 α[i] == α[m−1−i],故位置 i 与位置 m−1−i 实际共享同一决策变量。
合并对称位置:对每个 i ∈ [0, ⌊(m−1)/2⌋],我们需共同决定 α[i](同时决定 α[m−1−i])。此时,该字符将参与计算所有字符串在位置 i 和位置 m−1−i 上的误差贡献。即:
总误差中与 α[i] 相关的部分 = Σk (|sk[i] − c| + |sk[m−1−i] − c|),其中 c ∈ ['a', 'z']。
该表达式是关于 c 的分段线性凸函数,其最小值在所有 2n 个字符(含重复)的中位数处取得。由于字符集离散且有序('a'=0, ..., 'z'=25),我们可统计频次后线性扫描求中位数索引。
字典序最小保证:中位数可能不唯一(例如偶数个元素时,任意介于两个中间值之间的数都最小化绝对偏差和)。但题目要求字典序最小解,因此我们应选择满足最小误差条件的最小字符。幸运的是,上述频次累加求中位数的过程天然返回最小可行中位数下标(因从 'a' 开始累加计数,首次使累计频次 ≥ n 即停止),恰好满足字典序要求。
以下是完整实现(含边界处理):
static String solve(List<string> list) {
int n = list.size();
int m = list.get(0).length();
StringBuilder sb = new StringBuilder();
// 只需确定前半部分(含中心,当 m 为奇数时)
int mid = (m + 1) / 2;
for (int i = 0; i = n(注意:共 2n 个字符,中位数定义为第 n 小元素)
int total = 0;
int medianIdx = 0;
for (; medianIdx = n) break; // 第 n 小元素落在该字符上(因共 2n 个样本,中位区间为第 n & n+1 个,取小者保字典序)
}
sb.append((char)('a' + medianIdx));
}
// 构建完整回文:前半部分 + 反转后的前半部分(跳过中心字符)
String half = sb.toString();
String rightHalf = new StringBuilder(half).reverse().substring(m % 2);
return half + rightHalf;
}</string>
注意事项:
- 时间复杂度:O(n × m + 26 × m/2) = O(n × m),满足约束
n × m ≤ 2×10⁵; - 空间复杂度:O(1) 额外空间(固定大小频次数组);
- 正确处理奇偶长度:当
m为奇数时,中心位i == j,只统计一次;substring(m % 2)自动跳过中心字符以避免重复; - 严格满足“字典序最小”:因中位数扫描从
'a'开始,首个达标字符即为所求。
该解法摒弃暴力枚举,基于数学优化(L1 中位数性质)与回文对称性,兼具高效性与正确性。










