C语言/数据结构贪心算法题解:字符串趋同——逐位统计最高频率求最小修改代价

问题描述

小明的学校正在举办一场"字符串趋同"游戏,每个班级需要将自己的字符串通过最少次数的字符修改操作变得完全相同。每位同学初始有一个由小写字母组成的字符串,每次操作可以选择任意一位同学,修改其字符串中的任意一个字符(可以改为任意小写字母)。但是每次修改的代价为1,不同位置的修改代价独立计算。

作为班级的算法小能手,小明需要设计一个高效的算法来计算让所有字符串趋同的最小总代价。注意,最终所有字符串必须完全相同(可以是任意由小写字母组成的字符串,不限于原始字符串之一),且长度保持不变(不允许增删字符,只能修改)。

要求:

  1. 设计一个时间复杂度为 O(n * m) 的算法,其中 n 是字符串数量,m 是每个字符串的长度(假设所有字符串长度相同)。
  2. 尽量减少额外空间的使用,以体现算法优化能力。

测试样例

样例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;
}

运行结果

相关推荐
水饺编程1 小时前
第1章:开发环境搭建,在 Windows 中安装 Git
linux·c语言·汇编·git·ubuntu
H.莓飛1 小时前
【Linux】命令行参数、环境变量与程序地址空间
linux·c语言·chrome·后端·centos
山下梅子酒2251 小时前
洛谷-入门-B2080
c语言
Tisfy2 小时前
LeetCode 0678.有效的括号字符串:O(n)+O(1)一次遍历
算法·leetcode·字符串·题解·贪心·括号匹配
红豆诗人2 小时前
C++二叉搜索树:查找、插入和删除为什么这样写
数据结构·c++·算法
H.莓飛3 小时前
【数据结构】堆_OJ题
linux·数据结构·算法
大侠归来5 小时前
C 语言 | 在函数中操作数组
c语言·c++·算法
7yewh11 小时前
SLAM 三维空间刚体运动(2)
数据结构·人工智能·机器人·嵌入式·slam
leikooo12 小时前
用餐厅和盘子理解栈和堆
java·数据结构·链表·rust