- 朴素想法是在遍历中找窗口内的最大值,使用堆排序,最好的时间复杂度是
O
(
n
l
o
g
k
)
O(nlogk)
O(nlogk),其中
k
k
k为窗口大小,这种做法会导致很多重复计算
- 可以使用
deque
维护一个包含数组下标的双端链表,此链表在头尾的插入删除均为
O
(
1
)
O(1)
O(1),此链表中下标对应的值是递减的
这样在找当前窗口最大值时只需返回头节点 - 复杂度:时间
O
(
n
)
O(n)
O(n)(一次遍历),空间
O
(
k
)
O(k)
O(k)(deque)
class Solution {
public:
vector<int> maxInWindows(const vector<int>& num, unsigned int size) {
vector<int> ret;
if(size==0||size>num.size()) return ret;
deque<int> dq;
for(int i=0;i<num.size();++i){
while(!dq.empty() && num[dq.back()] < num[i]) dq.pop_back();
dq.push_back(i);
if(i-dq.front()>=size) dq.pop_front();
if(i+1>=size) ret.push_back(num[dq.front()]);
}
return ret;
}
};
- 二分找上下界
- 复杂度:时间
O
(
l
o
g
n
)
O(logn)
O(logn)(两次二分),空间
O
(
1
)
O(1)
O(1)
- 可以直接使用stl的upper_bound和lower_bound
class Solution {
public:
int GetNumberOfK(vector<int> nums ,int target) {
return upper_bound(nums.begin(), nums.end(), target) - lower_bound(nums.begin(), nums.end(), target);
}
};
- 手动二分
- 注意计算mid时的
int
越界问题,不能使用
(
r
+
l
)
/
2
(r+l)/2
(r+l)/2,要用
l
+
(
r
−
l
)
/
2
l+(r-l)/2
l+(r−l)/2,虽然这里限制了n的大小,但还是要注意
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int lb,rb;
int l=0,r=data.size();
while(l<r){
int mid = l+(r-l)/2;
if(data[mid]>=k) r=mid;
else l=mid+1;
}
lb=l;
l=0,r=data.size();
while(l<r){
int mid = l+(r-l)/2;
if(data[mid]>k) r=mid;
else l=mid+1;
}
rb=l;
return rb-lb;
}
};
今天学到的知识