题目来源
题目描述
题目解析
暴力
首先,观察题目给定的范围,list1 和 list2 的长度不超过 1000,所以,我们可以考虑使用暴力来求解。
使用暴力的话,我们需要记录最小索引和。具体来说,我们可以先遍历list1,再在list2中找到相同的字符串,如果存在,则让两者的索引相加,和最小索引和相对比,如果小,则替换之并清除结果集且把当前值加入结果集,如果相等,则加入结果集。
vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) {
std::vector<std::string> ans;
int min = std::numeric_limits<int>::max();
for (int i = 0; i < list1.size(); ++i) {
for (int j = 0; j < list2.size(); ++j) {
if(list1[i] == list2[j]){
int t = i + j;
if(t == min){
ans.emplace_back(list1[i]);
}else if(t < min){
min = t;
ans.clear();
ans.emplace_back(list1[i]);
}
}
}
}
return ans;
}
哈希表
方法一的处理过程中可以看到,对于list1中的字符串,每次都要从list2中从头开始查找,那么,有没有什么方法可以优化一下呢?
我们可以先把一个链表中的字符串以及索引表用哈希存储起来,这样,再遍历另一个列表,就可以使用O(1) 的时间快速查找到前面的列表中是否存在了,从而降低时间复杂度。
vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) {
std::map<std::string, int> mapper;
for(int i = 0; i < list1.size(); i++){
mapper[list1[i]] = i;
}
std::vector<std::string> ans;
int min = std::numeric_limits<int>::max();
for (int j = 0; j < list2.size(); ++j) {
if(mapper.count(list2[j])){
int t = j + mapper[list2[j]];
if(t == min){
ans.emplace_back(list2[j]);
}else if(t < min){
min = t;
ans.clear();
ans.emplace_back(list2[j]);
}
}
}
return ans;
}
优化:问题是,如果list1非常大,list2特别小,那么保存list1到哈希表的代价更大,因此,我们可以考虑只保存长度更小的哈希表
vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) {
if(list1.size() > list2.size()){
return findRestaurant(list2, list1);
}
std::map<std::string, int> mapper;
for(int i = 0; i < list1.size(); i++){
mapper[list1[i]] = i;
}
std::vector<std::string> ans;
int min = std::numeric_limits<int>::max();
for (int j = 0; j < list2.size(); ++j) {
if(mapper.count(list2[j])){
int t = j + mapper[list2[j]];
if(t == min){
ans.emplace_back(list2[j]);
}else if(t < min){
min = t;
ans.clear();
ans.emplace_back(list2[j]);
}
}
}
return ans;
}