写在前面:
目前已经写了:
力扣hot100笔记(1):42.接雨水。239.滑动窗口最大值。
一、42.接雨水
时间复杂度:O(n)
思路:
根据示例图观察可得一个柱子接的雨水量=min(它左侧最高柱子高度,它右侧最高柱子高度)-它本身高度。于是用双指针的方法,维护leftMax和rightMax两个变量,left,right两个指针。当left所指向的柱子高度小于right所指向柱子的高度时,分为两种情况:
(1)left和right都指向初始位置,则leftMax一定会小于rightMax,则当前柱子雨水量=leftMax-height[left],并且left++。
(2)当不指向初始位置时,left之前的位置已经有leftMax一定小于rightMax,因为左右指针不相撞,所以之前位置的rightMax值一定在当前left右侧,如果当前left位置柱子高度也低于右侧则仍然是leftMax一定会小于rightMax。
即(1)(2)情况都是柱子雨水量=leftMax-height[left]。
若是left所指向柱子高度大于right所指向柱子的高度时候同理。
代码:
cpp
class Solution {
public:
int trap(vector<int>& height) {
int left=0;
int n=height.size();
int right=n-1;
int leftMax=height[0];
int rightMax=height[n-1];
int ans=0;
while(left<right){
leftMax=max(leftMax,height[left]);
rightMax=max(rightMax,height[right]);
if(height[left]<height[right])
{
ans+=(leftMax-height[left]);
left++;
}
else
{
ans+=(rightMax-height[right]);
right--;
}
}
return ans;
}
};
二、239.滑动窗口最大值
时间复杂度O(n)
思路:
取一个双端队列,内部存储的是nums内下标。
遍历nums数组,
(1)当滑动窗口未达到指定k值的时候,i直接尾插入队列,如果尾部值小于等于nums[i]时,因为i的有效空间比队列内的值更长(队列内的值都在i的前面,比如i在遍历到i=8的时候才脱离滑动窗口,队列内其他值在遍历到i=8之前就已经脱离),并且i的值大于等于尾部值,故尾部值对答案没有影响,可以直接pop。
(2)当滑动窗口达到指定k值的时候,尾部仍然照上方法处理即可保证队列内部存储顺序为从大到小。在此之外还需要考虑头部最大这个值是否在有效期内,不在即pop。
代码:
cpp
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int>ans;
deque<int>q;
int n=nums.size();
for(int i=0;i<k;i++)
{
while(!q.empty()&&nums[i]>=nums[q.back()]){
q.pop_back();
}
q.push_back(i);
}
ans.push_back(nums[q.front()]);
for(int i=k;i<n;i++){
while(!q.empty()&&i-q.front()>=k){
q.pop_front();
}
while(!q.empty()&&nums[i]>nums[q.back()]){
q.pop_back();
}
q.push_back(i);
ans.push_back(nums[q.front()]);
}
return ans;
}
};