问题描述
小明的学校正在举办一场"字符串趋同"游戏,每个班级需要将自己的字符串通过最少次数的字符修改操作变得完全相同。每位同学初始有一个由小写字母组成的字符串,每次操作可以选择任意一位同学,修改其字符串中的任意一个字符(可以改为任意小写字母)。但是每次修改的代价为1,不同位置的修改代价独立计算。
作为班级的算法小能手,小明需要设计一个高效的算法来计算让所有字符串趋同的最小总代价。注意,最终所有字符串必须完全相同(可以是任意由小写字母组成的字符串,不限于原始字符串之一),且长度保持不变(不允许增删字符,只能修改)。
要求:
- 设计一个时间复杂度为 O(n * m) 的算法,其中 n 是字符串数量,m 是每个字符串的长度(假设所有字符串长度相同)。
- 尽量减少额外空间的使用,以体现算法优化能力。
测试样例
样例1:
输入:
strs = ["abc", "adc", "aec"]输出:2解释:对于每个位置独立计算最小修改代价:
- 位置0:所有字符都是 'a',不需要修改(代价0)
- 位置1:字符有 'b','d','e',出现次数最多的是任意字符(但频率均为1),最小代价为 3 - 1 = 2(即需要修改2个字符)
- 位置2:所有字符都是 'c',不需要修改(代价0) 总最小代价为 0 + 2 + 0 = 2。
样例2:
输入:
strs = ["a", "b", "c"]输出:2解释:只有一个位置,字符为 'a','b','c',每个字符出现1次。最小代价为 3 - 1 = 2(即需要修改2个字符)。
样例3:
输入:
strs = ["hello", "hello", "hello"]输出:0解释:所有字符串已经相同,每个位置字符都相同,修改代价均为0。
约束条件
- 1 ≤ strs.length ≤ 100
- 1 ≤ strsi.length ≤ 100
- 所有字符串长度相同
- 字符串仅由小写英文字母组成
提示
- 考虑对字符串的每个位置独立处理。
- 对于每个位置,统计该位置上所有字符的出现频率,选择出现频率最高的字符作为目标字符,则该位置的最小修改代价为 n - max_frequency(其中 n 是字符串数量)。
- 总最小代价是所有位置的最小修改代价之和。
程序代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int minCost(char** strs, int strsSize) {
if (strsSize <= 1) return 0;
int n = strsSize;
int m = strlen(strs0);
int totalCost = 0;
// 逐位处理
for (int j = 0; j < m; j++) {
int count26 = {0};
// 统计该位置各字符频率
for (int i = 0; i < n; i++) {
countstrs\[ij - 'a']++;
}
// 找最大频率
int maxFreq = 0;
for (int k = 0; k < 26; k++) {
if (countk > maxFreq) {
maxFreq = countk;
}
}
// 该位置代价 = n - maxFreq
totalCost += n - maxFreq;
}
return totalCost;
}
int main() {
char* strs1\[\] = {"abc", "adc", "aec"};
printf("%d\n", minCost(strs1, 3)); // 2
char* strs2\[\] = {"a", "b", "c"};
printf("%d\n", minCost(strs2, 3)); // 2
char* strs3\[\] = {"hello", "hello", "hello"};
printf("%d\n", minCost(strs3, 3)); // 0
return 0;
}
cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int minCost(char** strs, int strsSize) {
if (strsSize <= 1) return 0;
int n = strsSize;
int m = strlen(strs[0]);
int totalCost = 0;
// 逐位处理
for (int j = 0; j < m; j++) {
int count[26] = {0};
// 统计该位置各字符频率
for (int i = 0; i < n; i++) {
count[strs[i][j] - 'a']++;
}
// 找最大频率
int maxFreq = 0;
for (int k = 0; k < 26; k++) {
if (count[k] > maxFreq) {
maxFreq = count[k];
}
}
// 该位置代价 = n - maxFreq
totalCost += n - maxFreq;
}
return totalCost;
}
int main() {
char* strs1[] = {"abc", "adc", "aec"};
printf("%d\n", minCost(strs1, 3)); // 2
char* strs2[] = {"a", "b", "c"};
printf("%d\n", minCost(strs2, 3)); // 2
char* strs3[] = {"hello", "hello", "hello"};
printf("%d\n", minCost(strs3, 3)); // 0
return 0;
}
运行结果
