无法理解变位词最小删除数问题解法逻辑,求技术解析
刚接触竞赛编程的话,这段代码的计数逻辑确实容易让人摸不着头脑,我来一步步给你拆解开讲清楚~
首先得明确问题核心:要让两个字符串变成变位词,其实就是要让它们剩下的字符完全一样(只是顺序可以不同),所以我们需要先统计每个字符串里每个字母出现的次数,再算出两个字符串中字母数量的差异——差异的总和就是需要删除的最少字符数。
第一个for循环:统计第一个字符串的字母频率
for (int i = 0; i < len1; i++) { cnt1[c1[i] - 97]++; }
这里的关键点是c1[i] - 97:因为小写字母'a'的ASCII码是97,所以用当前字符减去97,就能把所有小写字母映射成0到25的索引(比如'a'对应0,'b'对应1,一直到'z'对应25)。这个循环做的事情就是,遍历第一个字符串的每一个字符,把对应索引位置的计数加1。比如如果第一个字符串是"hello",那cnt1[7](对应'h')会变成1,cnt1[4](对应'e')变成1,cnt1[11](对应'l')变成2,cnt1[14](对应'o')变成1,其他位置都是0。
第二个for循环:统计第二个字符串的字母频率
for (int i = 0; i < len2; i++) { cnt2[c2[i] - 97]++; }
这个循环和第一个逻辑完全一致,只是把统计对象换成了第二个字符串str2,结果存在cnt2数组里。比如第二个字符串是"world",那cnt2[22]('w')、cnt2[14]('o')、cnt2[17]('r')、cnt2[11]('l')、cnt2[3]('d')各加1。
最后计算总删除次数
当我们有了两个字母频率数组后,只需要遍历0到25的每个索引,计算两个数组对应位置的差值的绝对值,再把这些绝对值加起来,就是答案啦。比如上面的"hello"和"world",相同的字母只有'l'和'o':'l'在两个数组里分别是2和1,差值绝对值是1;'o'分别是1和1,差值是0;其他字母的差值绝对值都是1(因为一个有一个没有),加起来就是1+0+1+1+1+1+1=6,也就是需要删除6个字符("hello"删掉h、e,"world"删掉w、r、d,再删掉"hello"里的一个'l',剩下的"lo"和"ol"就是变位词)。
内容的提问来源于stack exchange,提问作者Vishank Shah

