最近的请求次数
写一个 RecentCounter 类来计算最近的请求。
它只有一个方法:ping(int t),其中 t 代表以毫秒为单位的某个时间。
返回从 3000 毫秒前到现在的 ping 数。
任何处于 [t - 3000, t] 时间范围之内的 ping 都将会被计算在内,包括当前(指 t 时刻)的 ping。
保证每次对 ping 的调用都使用比之前更大的 t 值。
输入:inputs = [“RecentCounter”,“ping”,“ping”,“ping”,“ping”], inputs = [[],[1],[100],[3001],[3002]]
输出:[null,1,2,3,3]
解题思路(参考题解)
计算t时刻之前的ping值在 [t - 3000, t] 时间范围之内的个数
1的话,区间为[-2999,1]有一个(1),100:[-2900,100]有两个(1,100).。。。。
注意:每次对 ping 的调用都使用比之前更大的 t 值。只需要看队列前面的数是否比t-3000小
代码
class RecentCounter {
public:
queue<int> q;
RecentCounter() {
}
int ping(int t) {
//保证每次对 ping 的调用都使用比之前更大的 t 值
q.push(t);
//只要队列前面的数小于t-3000就出队,如果出现比它大的就证明后面的数都比t-3000大
while(!q.empty())
{
if(q.front()<t-3000)
q.pop();
else
break;
}
return q.size();
}
};
剑指 Offer 59 - I. 滑动窗口的最大值
给定一个数组 nums
和滑动窗口的大小 k
,请找出所有滑动窗口里的最大值。
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
解题思路
暴力解法,自己写的垃圾解法
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ma;
int max;
for(vector<int>::iterator it=nums.begin();it!=nums.end();it++)
{
max=*it;
for(int i=0;i<k;i++)
{
if(it==nums.end()) break;
if(*it>max) max=*it;
it++;
}
ma.push_back(max);
if(it==nums.end()) break;
it-=k;
}
return ma;
}
int main()
{
vector<int> nums;
vector<int> n;
int k,temp;
for(int i=0;i<8;i++)
{
cin>>temp;
nums.push_back(temp);
}
cin>>k;
n=maxSlidingWindow(nums,k);
for(vector<int>::iterator it=n.begin();it!=n.end();it++)
{
cout<<*it<<" ";
}
return 0;
}
参考题解
vector<int> maxSlidingWindow(vector<int>& nums, int k)
{
vector<int> ans;
int n=nums.size();
//数组没有元素时
if(!n) return ans;
//队列存储下标,单调递减
deque<int> d;//定义一个双端队列,前面后面都可以push和pop
for(int i=0;i<n;i++)
{
//当队列不为空,单调队列的最小值小于数组中的元素时
//队列中只保存数组最大值的下标
while(!d.empty()&&nums[i]>=nums[d.back()])
d.pop_back();
//删除无效的索引,即超出滑动窗口最前面的下标
while(!d.empty()&&d.front()<i-k+1)
d.pop_front();
d.push_back(i);
//将每次数组中的最大值push进输出数组
if(i>=k-1) ans.push_back(nums[d.front]);
}
return ans;
}