【发布时间】:2020-03-08 21:07:06
【问题描述】:
背景:
我今天在一次在线练习面试中被问到这个问题,我很难找到一个自定义比较器来排序。问题来了
问题:
实现一个文档扫描函数wordCountEngine,它接收一个字符串文档并返回其中所有唯一单词的列表及其出现次数,按出现次数降序排列。如果两个或多个单词的计数相同,则应按照它们在原句中的顺序进行排序。假设所有字母都是英文字母。你的函数应该不区分大小写,例如,“Perfect”和“perfect”这两个词应该被认为是同一个词。
引擎应该去掉标点符号(即使在单词中间)并使用空格来分隔单词。
分析解决方案的时间和空间复杂性。尝试在保持多项式空间复杂度的同时优化时间。
例子:
input: document = "熟能生巧。你只会 通过练习获得完美。练习吧!”
输出:[[“练习”,“3”],[“完美”,“2”], ["makes", "1"], ["youll", "1"], ["only", "1"], ["get", "1"], ["by", "1"], ["just", "1"] ]
我的想法:
我想做的第一个想法是首先将没有标点符号且全部小写的字符串放入字符串向量中。然后我使用unordered_map 容器来存储字符串和它的出现次数。我遇到困难的地方是创建一个自定义比较器,以确保如果我有一个具有相同计数的字符串,那么我会根据它在实际给定字符串中的优先级对其进行排序。
代码:
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <sstream>
#include <iterator>
#include <numeric>
#include <algorithm>
using namespace std;
struct cmp
{
bool operator()(std::string& word1, std::string& word2)
{
}
};
vector<vector<string>> wordCountEngine( const string& document )
{
// your code goes here
// Step 1
auto doc = document;
std::string str;
remove_copy_if(doc.begin(), doc.end(), std::back_inserter(str),
std::ptr_fun<int, int>(&std::ispunct));
for(int i = 0; i < str.size(); ++i)
str[i] = tolower(str[i]);
std::stringstream ss(str);
istream_iterator<std::string> begin(ss);
istream_iterator<std::string> end;
std::vector<std::string> vec(begin, end);
// Step 2
std::unordered_map<std::string, int> m;
for(auto word : vec)
m[word]++;
// Step 3
std::vector<std::vector<std::string>> result;
for(auto it : m)
{
result.push_back({it.first, std::to_string(it.second)});
}
return result;
}
int main() {
std::string document = "Practice makes perfect. you'll only get Perfect by practice. just practice!";
auto result = wordCountEngine(document);
for(int i = 0; i < result.size(); ++i)
{
for(int j = 0; j < result[0].size(); ++j)
{
std::cout << result[i][j] << " ";
}
std::cout << "\n";
}
return 0;
}
如果有人可以帮助我学习如何为此代码构建自定义比较器,我将不胜感激。
【问题讨论】:
-
尝试使用
std::vector<std::pair<std::string, int>>作为result