先看一道面试题。
某公司中有N名员工,给定所有员工工资的清单,财务人员要按照持定的顺序排列员工的工资,他按照工资的频次降序排列,即给定清单中所有频次较高的工资将在频次较低的工资之前出现,如果相同数量的员工都有相同的工资,则将按照给定清单中该工资第一次出现的顺序排列。
写一算法来帮助财务人员排列员工工资的顺序。
输入:
该函数/方法的输入包括两个参数——
num,一个整数,表示员工的人数。
salaries,一个正整数列表,表示N名员工的工资。
输出:
返回一个正整数列表, 该列表按照员工工资的频次排序。
约朿条件:
1 <= num <= 10^5
1 <= salaries[i]<=10^9
0 <= i < num
示例如下
输入:
num=19
salaries=[10000,20000,40000,30000,30000,30000,40000,20000,50000,50000,50000,50000,60000,60000,60000,70000,80000,90000,100000]
输出:
[50000,50000,50000,50000,30000,30000,30000,60000,60000,60000,20000,20000,40000,40000,10000,70000,80000,90000,100000]
代码:
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> salaryfrequeny(int num, int *salaries)
{
unordered_map<int, int> cntm;
unordered_map<int, int> posm;
vector<int> res;
vector<pair<int, int>>cntv;
for (int i = 0; i < num; i++) {
if (cntm.find(salaries[i]) != cntm.end()) {
cntm[salaries[i]]++;
}
else {
cntm[salaries[i]] = 1;
posm[salaries[i]] = i;
}
}
for (auto iter = cntm.begin(); iter != cntm.end(); iter++) {
cntv.push_back(make_pair(iter->first, iter->second));
}
/* sort(cntv.begin(), cntv.end(), [posm](const pair<int, int>&x, const pair<int, int>&y) ->int {return (x.second > y.second) || (x.second == y.second && posm.at(x.first) < posm.at(y.first)); }); */
sort(cntv.begin(), cntv.end(), [&posm](const pair<int, int>&x, const pair<int, int>&y) ->int {return (x.second > y.second) || (x.second == y.second && posm[x.first] < posm[y.first]); });
for (auto iter = cntv.begin(); iter != cntv.end(); iter++) {
for (int i = 0; i < iter->second; i++) {
res.push_back(iter->first);
}
}
return res;
}
发现将lambda的捕获修改为[posm],即如下传值就报错:
sort(cntv.begin(), cntv.end(), [posm](const pair<int, int>&x, const pair<int, int>&y) ->int {return (x.second > y.second) || (x.second == y.second && posm[x.first] < posm[y.first]); });
报错信息如下:
但我这里一开始声明的posm不是const啊,怎么回事?
原来是lambda表达式搞的鬼,当捕获为map/unordered_map的值时,lambda表达式会默认转换为const map/const unordered_map。但又为什么会这样转换呢?
我查看了下C++标准:
map和unordered_map下的operator[],当关键字不存在则会进行插入,这样当有关键字不存在时就会修改了posm的值,所以当捕获为map/unordered_map的值时,lambda表达式干脆默认转换为const map/const unordered_map。这样编译器就会报错了。
另外,当捕获为map/unordered_map的值时,可以使用at(),即
sort(cntv.begin(), cntv.end(), [posm](const pair<int, int>&x, const pair<int, int>&y) ->int {return (x.second > y.second) || (x.second == y.second && posm.at(x.first) < posm.at(y.first)); });