目录
前言
今天来总结力扣上的两道习题,简单题与中等题各一道,并且都提供了优化后的方法,通过优化后的效率都提升很大。
简单题:2085.统计出现过一次的公共字符串
方法一:使用两个哈希表计数
常规方法是使用两个哈希表统计两个字符串数组中每个字符串出现的次数,然后遍历其中一个哈希表,如果某个字符串在另一个哈希表中出现了一次,且在当前哈希表中也出现了一次,则答案加一。
class Solution {
public:
int countWords(vector<string>& words1, vector<string>& words2) {
unordered_map<string, int> freq1, freq2;
for (const string& w: words1) {
++ freq1[w];
}
for (const string& w: words2) {
++ freq2[w];
}
// 遍历 words1 出现的字符并判断是否满足要求
int res = 0;
for (const auto& [w, cnt1] : freq1) {
if (cnt1 == 1 && freq2[w] == 1) {
++ res;
}
}
return res;
}
};
方法二:使用一个哈希表计数(优化)
针对常规方法,我们可以对其进行优化,简化成只使用一个哈希表进行计数,并且对效率也可以进行优化。我们可以只使用一个哈希表 counter1 进行统计,counter1哈希表先用来统计words1中字符串出现的频率,紧接着可以通过words2对counter1中的字符串进行筛选,根据题目要求,我们可以只选择counter1中出现不超过一次的字符串,然后最后遍历哈希表,如果某个字符串在哈希表中的值为0,则答案加一。
class Solution {
public:
int countWords(vector<string>& words1, vector<string>& words2) {
auto counter1 = unordered_map<string_view, int>();
for (const auto &w : words1) {
++ counter1[w];
}
for (const auto &w : words2) {
if(counter1[w] <= 1){
-- counter1[w];
}
}
int cnt = 0;
for (const auto &[_, v] : counter1) {
if (v == 0) {
++ cnt;
}
}
return cnt;
}
};
该方法优化后对于时间、空间复杂度都有了很大的提升。
中等题:739.每日温度
方法一:暴力法
常规的暴力法会使得时间复杂度来到O(n * n)而导致超时,通过优化可以降到O(n * m)而通过案例测评,这里不对暴力法进行过多的讨论,感兴趣的伙伴可以去官方题解进行查看。
方法二:单调栈
通过维护一个只存储下标的单调栈进行处理,从栈底到栈顶的下标对应的温度列表中的温度依次递减。如果一个下标在单调栈里,则表示尚未找到下一次温度更高的下标。
当栈中元素为空时,当前元素直接入栈;
当栈中有元素时,将当前的元素依次与栈顶的元素进行大小判断:
(1)栈顶元素大于当前元素时,将当前元素直接入栈;
(2)栈顶元素小于当前元素时,将两者下标进行做差运算,得到的结果返回到数组列表中相对应的下标。
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
int n = temperatures.size();
vector<int> ans(n);
stack<int> s;
for(int i = 0; i < n; ++ i){
while(!s.empty() && temperatures[i] > temperatures[s.top()]){
int Index = s.top();
ans[Index] = i - Index;
s.pop();
}
s.push(i);
}
return ans;
}
};
方法三:动态规划
倒着遍历temperatures,每次向后找下一个出现最高温度的日子,例如当前在找第i天的答案,从第j = i + 1天开始,如果temperatures[j]>temperatures[i],那么ans[i]就等于j - i;否则,找到下一个j,也就是j += ans[j](因为是倒着求解的,ans[i+1~最后一天]已经确定)。
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
int n = temperatures.size();
vector<int> ans(n);
int i = 0,j = 0;
for(i = n - 2; i >= 0; -- i)//从右往左遍历
{
int j = i+1;
while(j < n)
{
if(temperatures[j] > temperatures[i])//找到更高的温度
{
ans[i] = j - i;
break;
}
else//未找到更高的温度,对[i+1,n-1]的范围内进行搜索
{
if(ans[j] == 0) //后面的温度没有当前高,表明此前的温度未升高
{
ans[i] = 0;
break;
}
j += ans[j];//根据计数的时间跳转到升高的温度点
}
}
}
return ans;
}
};
该方法的测评截图: