获取给定数字集中具有相同数字频率的组数

时间:2016-04-22 18:05:41

标签: c++ algorithm

这是我在采访中遇到的一个问题,我想知道最好的方法是什么。 给出了一个数字列表,我们需要确定每个数字的数字具有相同频率的组的数量并打印这些组。例如: 例如,如果数字是: 1 10 3 33

共有4组:

G1={1}has one 1. 
G2={3} has one 3. 
G3={10}has one 1 and one 0. 
G4={33}as two 3s.

我在考虑保留地图矢量。地图将包含每个数字的频率。现在,当一个数字出现时,如果存在一个具有当前数字相同频率图的条目,则检查整个向量。如果它存在附加到列表。我无法确定如何识别组以及打印它。有没有更好的方法来解决这个问题,因为我觉得我的解决方案效率很低。

2 个答案:

答案 0 :(得分:2)

考虑一下hash-table的工作原理。您将散列函数应用于项目,并根据此散列值将项目分配给插槽。但是可能会发生两个不同的项具有相同的哈希值。在这种情况下,哈希表将创建具有相同哈希值的列表。这称为碰撞。

在哈希表实现中,我们尝试避免冲突。但在这里它会很好地为你服务。如果您可以找到一个哈希函数,使得:同一组中的两个数字具有相同的哈希值,您可以轻松地对这些数字进行分组。

这种哈希函数的一个例子是:

  • 将数字转换为字符串
  • 按升序排序字符串

同一组中的所有数字都具有相同的哈希值。

示例实施:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;


unordered_map<string, vector<int>> group_numbers(vector<int> numbers) {
    unordered_map<string, vector<int>> results;
    for(auto n : numbers) {
        stringstream buffer;
        buffer << n;
        string hash;
        buffer >> hash;

        sort(begin(hash), end(hash));
        results[hash].push_back(n);
    }
    return results;
}


int main() {
    vector<int> numbers{1, 10, 3, 33, 133, 331, 313, 333};
    auto results = group_numbers(numbers);
    int group = 0;
    for(auto kv : results) {
        cout << "Group " << (++group) << " : ";
        copy(begin(kv.second), end(kv.second),
             ostream_iterator<int>(cout, " "));
        cout << "\n";
    }
}

然后在运行时打印:

Group 1 : 333
Group 2 : 133 331 313
Group 3 : 1
Group 4 : 10
Group 5 : 33
Group 6 : 3

答案 1 :(得分:0)

因此,如果我理解正确的问题,他们并不关心实际的数字。他们只是询问频率。因此,这将为我们提供std::map<int,int>,其中key是列表中的整数,valuekey中数字的频率。我们只需要将类别显示为具有1,2,3的值...或者可以检查哪个具有相等的value等。

#include <iostream>
#include <vector>
#include <map>

int main()
{
    std::vector<int> MyVec = { 1, 10, 3, 33 }; // sample data
    std::map<int, int> MyMap;

    for (int i = 0; i < MyVec.size(); i++) // fill the map with ALL the numbers first
        MyMap[MyVec[i]]++;

    for (auto itr = MyMap.begin(); itr != MyMap.end(); itr++) // increment each value based on the frequence of the digits found in the key
    {
        if (itr->first < 10) // it has one
            continue;
        else
        {
            int temp = itr->first;
            while (temp >= 10)
            {
                temp = temp % 10;
                itr->second++;
            }
        }
    }

    for (auto itr = MyMap.begin(); itr != MyMap.end(); itr++) // display
    {
        std::cout << "first: " << itr->first << " second: " << itr->second << "\n";
    }

    return 0;
}