题目
同时也是百度2018秋招的笔试题,LeetCode 451–根据字符出现频率排序的变形
题意为从一个乱序数组中,将其中的整数按照出现的频次多少来排列,比如输入为
[1,2,1,2,3,3,1,6,4,4,4,4],那么输出就应该为[4,4,4,4,1,1,1,2,2,3,3,6],
其中,如果某两个数字的出现频次相同,那么就按照输入用例中的原顺序排列
#include <iostream>
#include <set>
#include <map>
#include <vector>
using namespace std;
//自定义数据类型,用于记录数组中每个值,出现次数,和出现顺序(因为排序后不能影响原来顺序)
struct Data
{
int key; //原数组中的值
int count; //出现次数
int order; // 出现的顺序
Data(int K, int C, int O) : key(K), count(C), order(O) {}
};
//自定义set的函数对象(伪函数),给set容器排序
struct MyComp
{
bool operator()(const Data &d1, const Data &d2) const
{
if (d1.count != d2.count) //如果次数不等,按次数高到低排序
{
return d1.count > d2.count;
}
else //如果出现次数相等,按出现顺序由先到后排序
{
return d1.order < d2.order;
}
}
};
int main()
{
vector<int> v{ 1, 3, 3, 3, 1, 2, 1, 2, 6, 2, 4, 4, 4, 4 };
set<Data, MyComp> s; //set用于自定义排序,自定义数据类型是因为要记录三个值
map<int, pair<int, int>> m; //map用于记录kv
int order = 0;
for (int &i : v)
{
/*
带有一个键-值pair形参的insert版本将返回一个值:包含一个迭代器和一个bool值得pair对象,
其中迭代器指向map中具有相应键的元素,而bool值则表示是否插入了该元素。如果该键不
在容器中,则插入新元素,且bool值为ture;如果该键已在容器中,则其关联的值保持不
变,返回bool值为false。在这两种情况下,迭代器都将指向具有给定键的元素。*/
auto it = m.insert(make_pair(i, make_pair(1, order++)));
if (!it.second) //用返回的第二个对象判断是否插入成果,map中key值是唯一的,第二次会插入失败
{
order--; //插入失败则出现顺序减1
++(it.first->second.first); //出现次数加1
}
}
for (int &i : v) //将map值转入set,set自动排序,按照我们写的排序函数
{
s.insert(Data(i, m[i].first, m[i].second));
}
for (auto it = s.begin(); it != s.end(); ++it) //遍历set
{
for (int i = 0; i < it->count; i++)
{
cout << it->key << " " ;
}
// cout << it->key << "|" << it->count << "|" << it->order << endl;
//cout << it->key << endl; // 4 4 4 4 1 1 1 3 3 3 2 2 2 6
}
return 0;
}