2024.8.24
**每日一题**
3146.两个字符串的排列差,这道题是一道简单的模拟题,考察的是哈希表的知识,题目给出了两个字符串,我们只需要先将第一个字符串的对应字符和下标存到哈希表中,再遍历第二个字符串,依次累加位置的差的绝对值即可。
class Solution {
public:
int findPermutationDifference(string s, string t) {
unordered_map<char,int> f;
for(int i =0;i<s.length();i++){
f[s[i]]=i;
}
int ans = 0;
for(int i =0;i<t.length();i++){
ans+=abs(f[t[i]]-i);
}
return ans;
}
};
239.滑动窗口的最大值,这道题考察的是滑动窗口和队列的知识,刚开始看错题目了,求成了滑动窗口可能出现的最大值和出现最大值的滑动窗口内容,但题目要求的是滑动窗口每次滑动中内部的最大元素。可以考虑采用优先队列(大根堆)和单调队列(双端队列)的算法来解决。这里用的是单调队列的方法,即可以实现两端的加入和退出队列。用一个双端队列来记录未退出的最大值的下标,每次加入一个元素时,都依次对比队列中下标所对应的元素,如果把小于当前元素所对应的下标全部弹出队列,再将当前的元素下标加入。之后还需要对队列前端的元素进行检验,如果该元素下标不在当前滑动窗口的范围之内,那么就从前面弹出该元素。完成这两个步骤之后,队列的最前面的元素对应原数组的元素即为所求,依次遍历到数组末尾即可。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int n =nums.size();
deque<int> q;
for(int i =0;i<k;i++){
while(!q.empty()&&nums[i]>=nums[q.back()]){
q.pop_back();
}
q.push_back(i);
}
vector<int> ans={nums[q.front()]};
for(int i = k;i<n;i++){
while(!q.empty()&&nums[i]>nums[q.back()]){
q.pop_back();
}
q.push_back(i);
while(q.front()<=i-k){
q.pop_front();
}
ans.push_back(nums[q.front()]);
}
return ans;
}
};
300.最长递增子序列,这是一道非常经典的动态规划题目,一样是从前往后遍历更新状态,我们需要用一个数组来维护以每个元素结尾的最长上升子序列,结果最小是1,双循环遍历每个元素,如果在每个元素前找到比自己小的,那么就更新一次答案,最终答案为以每个元素为结尾的最长递增子序列中的最大值。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
if(n==0) return 0;
vector<int> dp(n,1);
int ans = 1;
for(int i = 0;i<n;i++){
for(int j =0;j<i;j++){
if(nums[j]<nums[i]){
dp[i]=max(dp[i],dp[j]+1);
ans=max(dp[i],ans);
}
}
}
return ans;
}
};