Codechef
当且仅当字符串中的所有字符出现的次数相等时,才认为字符串是平衡的。
给您一个字符串S;该字符串只能包含大写英文字母。您可以执行以下操作任意次数(包括零次):在S中选择一个字母并用另一个大写英文字母替换。注意,即使被替换的字母多次出现在S中,也只替换该字母的所选出现。
找到将给定字符串转换为平衡字符串所需的最小操作数。
例子:
输入:ABCB
在这里,我们可以用C替换A,得到:ABAB,其中字符串的每个字符出现2次。
因此,最小操作数=1
怎么把绳子弄好?
我可以对它应用动态编程吗?

最佳答案

我不认为你真的需要动态编程。
O(长度(S))时间内的一种方法:
在s上迭代,构建一个频率映射(从不同字母a–z到counts的映射)。对于您的ABCB示例,这将是A->1 B->2 C->1 D->0 E->0 ... Z->0,我们可以将其表示为数组[1, 2, 1, 0, 0, ..., 0]
我们之所以能做到这一点,是因为我们根本不关心字母的位置;ABCBABBC之间没有真正的区别,因为每个字母都可以通过用C替换它们的A来达到平衡。
对数组排序在您的示例中,它给出了[0, 0, ..., 0, 1, 1, 2]
我们之所以能做到这一点,是因为我们实际上并不关心哪个字母是哪个;在ABCBABDB之间没有真正的区别,因为每个字母都可以通过用另一个单子字母替换一个来平衡。
假设字符串是非空的(因为如果是,那么答案只有0),那么最终的平衡字符串将包含至少1个且最多26个不同的字母对于介于1和26之间的每个整数i,确定需要执行多少操作才能生成包含i个不同字母的平衡字符串:
首先,检查长度是i的倍数;如果不是,这是不可能的,所以跳到下一个整数。
接下来,计算长度/i,即最终平衡字符串中每个不同字母的计数。
为了计算需要执行多少操作,我们将检查需要增加的所有计数。(同样,我们可以检查需要减少的计数:它们必须匹配。)
我们只对排序数组的最后一个i元素感兴趣。在该点之前的任何元素都表示平衡字符串中不会出现的字母:计数已经为零并将保持为零,或者它们不是零但将减少为零不管怎样,因为我们只跟踪增长,我们可以忽略它们。
对于小于length(s)/i的最后一个i计数中的每一个,添加差异。这个和就是操作的数目。(注意,由于计数被排序,一旦到达计数大于或等于目标计数,就可以退出这个内循环。)
在第一个i之后,可以退出这个循环,它大于或等于原始S中不同字母的数目(除了我们必须跳过的i的值,因为它们不均匀地分割长度)。例如,如果长度=100,而原来的s有19个不同的字母,那么我们只需要考虑高达20的i。(向Eric Wang提出这些建议的帽子尖。)
最多返回26个金额中的最小值。(请注意,实际上并不需要存储所有的总和;您只需跟踪最小值即可。)

10-06 05:08
查看更多