本题是第342场周赛的Q3,竞赛分为1786,使用的方法是滑动窗口+哈希。从这个角度上讲这一题很像第567题。
在LC中,当数据量大小大于等于10^5(说明方法的复杂度必须低于O(n^2)),且涉及到子数组之中的计数,且数组元素的大小范围很有限时,可以考虑一下是否是 滑动窗口 + 哈希。
方法一. 滑动窗口+哈希
注意到 nums[i] 的大小是-50到50,也就是说可以用一个哈希数组记录子数组中每个数字的出现次数,检查所有的数字最多花去100的时间(也就是说常数时间)。通过滑动窗口使得每一次更新只进行两次改动和一次常数时间的检查,一共有 O(n)个数组,因此这个方法的总复杂度是O(100n)。
对于暴力算法,每一次都要check整个子数组,这样当子数组长度约等于n/2的时候,时间复杂度将会达到O(n^2),当n比较大的时候这个复杂度就无法接受了。
代码如下:
class Solution {
public:
vector<int> getSubarrayBeauty(vector<int>& nums, int k, int x) {
vector<int> ans;
int n = nums.size();
vector<int> tmp;
for(int i=0;i<k;i++) tmp.push_back(nums[i]);
sort(tmp.begin(),tmp.end());
if(tmp[x-1]<0)
ans.push_back(tmp[x-1]);
else
ans.push_back(0);
int left=0,right=k-1;
vector<int> cnt(200,0);
for(int i=0;i<k;i++)
cnt[tmp[i]+50]++;
while(right+1<n){
right++;
left++;
cnt[nums[left-1]+50]--;
cnt[nums[right]+50]++;
int i=0,tmp=x;
for(;tmp-cnt[i]>0;i++){
tmp -= cnt[i];
}
if(i-50<0) ans.push_back(i-50);
else ans.push_back(0);
}
return ans;
}
};