【问题标题】:Minimum number of steps to equalize distinct character of the string [duplicate]使字符串的不同字符相等的最小步骤数[重复]
【发布时间】:2021-04-13 16:37:59
【问题描述】:

我正在尝试编写这个要求用户输入字符串的程序,我的工作是打印出使字符串中不同字符的频率相等所需的最少步数。
示例
输入

6
aba  
abba  
abbc  
abbbc  
codedigger  
codealittle 

输出

1
0
1
2
2
3

这是我的程序:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;

int main()
{
    unordered_map<char, int >m;
    vector<int> vec1, vec2;
    string s;
    int n;

    cin >> n;
    cin.ignore();

    for (int i = 0; i < n; ++i)
    {
        m.clear();
        vec1.clear();
        getline(cin, s);
        for (int i = 0; i < s.size(); i++)
            m[s[i]]++;

        for (auto itr : m)
            vec1.push_back(itr.second);

        sort(vec1.begin(), vec1.end());

        int mid = vec1[vec1.size() / 2];
        int ans = 0;

        for (auto itr : vec1)
            ans += abs(mid - itr);

        vec2.push_back(ans);
    }
    for (int i = 0; i < vec2.size(); ++i)
        cout << vec2[i] << endl;
}

我尝试做的是针对每个测试用例:

  • 使用unordered_map 计算字符串中字符的频率。
  • 将地图的键值推送到向量。
  • 按升序对向量进行排序。
  • 计算向量的中间元素,以尽可能少的步长均衡不同的字符。
  • 结果将添加中间元素与当前元素之间的差异。
  • 将结果推送到另一个向量并打印出来。

但我的结果在测试用例 5 处是错误的:

1  
0  
1  
2  
3  // The actual result is 2
3  

我不明白为什么我得到错误的结果,谁能帮我解决这个问题?感谢您的帮助!

【问题讨论】:

  • 那么,当您使用调试器逐行执行代码时,您观察到了什么?所有变量都按照您的预期发生变化吗?
  • 您应该详细说明在每个步骤中允许执行哪些操作。例如,您可以添加一个新角色吗?
  • @Damien,不,您不能添加新字符,只需更改字符串的字符,使所有不同字符的频率相同。
  • 我不知道为什么这个问题被关闭了。我相信我理解 OP 的问题,并且我已经为它写了一个答案,我现在无法发布。在我看来,他/她的问题不是为什么他/她的代码“不起作用”,而是为什么算法不是最优的。
  • 我投票重新打开这篇文章的原因如下:代码应该做什么现在已经很清楚了。 OP 提出了一种非常接近于好的算法。我们有一个先生。我们有一个包含正确/错误答案的简单测试用例。

标签: c++ algorithm


【解决方案1】:

问题是您的算法没有找到最佳步数。

考虑一下您得到错误答案的字符串:codedigger。它有 4 个频率为 1 (coir) 的字母和 3 个频率为 2 (ddeegg) 的字母。 最佳方法是 not 将频率为 2 的一半字母转换为某个新字符(字符串中不存在)以使所有频率为 1。据我了解,您的实现是计算这将需要。 相反,考虑一下:

c[o]dedigge[r]

如果我将o 替换为c 并将r 替换为i,我得到:

ccdediggei

已经均衡了字符频率。您会注意到我只执行了 2 次编辑。

所以没有给你一个解决方案,我相信这仍然可以回答你的问题?也许考虑到这一点,您可以提出一种不同的算法来找到最佳的编辑数量。

【讨论】:

    【解决方案2】:

    您的代码正确地测量了每个字母的频率,作为重要信息。

    然后,主要有两个问题:

    • 目标值(最终均衡频率)不一定等于中值。特别是,这个值必须除以字母的总数
    • 对于给定的目标高度值,您计算的步数不正确。您必须注意不要计算两次相同的突变。而且,通式不同,取决于最终不同字母的个数是否相等、小于或大于原始字母个数。

    以下代码关注的是正确性,而不是过多的效率。它考虑了目标高度(频率)的所有可能值,即字母总数的所有除数。

    如果效率确实是一个问题(帖子中没有提到),那么例如可以认为最佳值不太可能与初始平均频率值相差甚远。

    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <numeric>
    #include <unordered_map>
    
    
    //  calculates the number of steps for a given target
    //  This code assumes that the frequencies are sorted in descending order. 
    
    int n_steps (std::vector<int>& freq, int target, int nchar) {
        int sum = 0;
        int n = freq.size();
        int m = nchar/target;   // new number of characters
        
        int imax = std::min (n, m);
        for (int i = 0; i < imax; ++i) {
            sum += std::abs (freq[i] - target);
        }
        for (int i = imax; i < n; ++i) {
            sum += freq[i];
        }
        
        if (m > n) sum += m-n;
        sum /= 2;
        
        return sum;
    }
    
    int main() {
        std::unordered_map<char, int >m;
        std::vector<int> vec1, vec2;
        std::string s;
        int n;
    
        std::cin >> n;
        std::cin.ignore();
    
        for (int i = 0; i < n; ++i)
        {
            m.clear();
            vec1.clear();
            //getline(cin, s);
            std::cin >> s;
            for (int i = 0; i < s.size(); i++)
                m[s[i]]++;
    
            for (auto itr : m)
                vec1.push_back(itr.second);
    
            sort(vec1.begin(), vec1.end(), std::greater<int>());
            
            int nchar = s.size();
            int n_min_oper = nchar+1;
            for (int target = 1; target <= nchar; ++target) {
                if (nchar % target) continue;
                int n_oper = n_steps (vec1, target, nchar);
                if (n_oper < n_min_oper) n_min_oper = n_oper;
            }
            vec2.push_back(n_min_oper);
        }
        for (int i = 0; i < vec2.size(); ++i)
            std::cout << vec2[i] << std::endl;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      • 2014-07-19
      • 2014-05-11
      • 2014-09-30
      • 2015-01-05
      相关资源
      最近更新 更多