Reputation: 5237
This is a question I had got in an interview and I was wondering what the best approach would be. A list of numbers is given and we need to identify the number of groups in which the digits of each number have same frequency and print the groups. For example: For example if numbers are: 1 10 3 33
There are 4 groups:
G1={1}has one 1.
G2={3} has one 3.
G3={10}has one 1 and one 0.
G4={33}as two 3s.
I was thinking of keeping a vector of maps. The maps will contain a frequency of each digit. Now when a number comes check in the entire vector if there exists an entry which will have a same frequency map of the current number. If it exists append to a list. I am not able to identify how i should identify the groups as well to print it. Is there a better way to solve this problem as I feel my solution is really inefficient.
Upvotes: 2
Views: 437
Reputation: 7996
Think about how hash-table works. You apply a hash function to the item and based on this hash value you assign the item to a slot. But it may happen that two different items have the same hash value. In that case the hash-table will create a list of the values with the same hash. This is called a collision.
In a hash-table implementation we try to avoid collision. But here it will serve you well. If you can find a hash function such that: two numbers in the same group have the same hash value, you could easily group the numbers.
An example of such a hash function is this:
All numbers in the same group will have the same hash value.
Example implementation:
#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";
}
}
Then when run it prints:
Group 1 : 333
Group 2 : 133 331 313
Group 3 : 1
Group 4 : 10
Group 5 : 33
Group 6 : 3
Upvotes: 2
Reputation: 9407
So if I understood the question right, they didn't care about the actual numbers. They are just asking about the frequency. Therefore, this will provide us with a std::map<int,int>
where key
is the whole number from the list and value
is the frequency of the numbers in that key
. We only need to display categories as whatever has value of 1, 2, 3.. or maybe check which has equal value
etc.
#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;
}
Upvotes: 0