题意:1,...,N个位置各有一朵花,开花时间是1,...,N的某一天且开花时间各不相同。问的第几天(earliest days)有两朵花开且这两朵花中间有k朵花且全部没开。
constraint是中间相隔k朵花,所以先把input转化position数组更直观些,position[i]表示位置i的开花时间。对于两朵花x,x+k+1,如果中间的k朵花都没开,那么中间k朵花的开花时间都比x,x+k+1的开花时间大。只需找到[x+1,x+k]的区间最小值,判断其是否大于max(position[x],position[x+k+1])即可。
求区间最小值,可以维护一个单调升的双端队列。对于position x,如果que左端在[x-k+,x]范围之外,则pop front,如果que右端的元素(index)对应的天数比position[x]大,那么将que pop back直到将x push进去后队列仍然是单调增的。这样,que最左端就是区间[x,x+k-1]对应的最小值。
class Solution {
public:
int kEmptySlots(vector<int>& flowers, int k) {
deque<int>que;
int arr[20010];//minimum value in interval [x,x+k]
int position[20010];
memset(arr,0,sizeof(arr));
memset(position,0,sizeof(position));
for(int i=0;i<flowers.size();i++)
{
position[flowers[i]-1]=i+1;
}
// for(int i=0;i<flowers.size();i++)
// {
// cout<<position[i]<<" ";
// }
// cout<<endl;
while(!que.empty())
{
que.pop_back();
}
//intialize
for(int i=0;i<k;i++)
{
while(!que.empty()&&position[que.back()]>position[i])
{
que.pop_back();
}
que.push_back(i);
}
// cout<<que.front()<<endl;
for(int i=k-1;i<flowers.size();i++)
{
while(!que.empty()&&que.front()<i-k+1)
{
que.pop_front();
}
while(!que.empty()&&position[que.back()]>position[i])
{
que.pop_back();
}
que.push_back(i);
arr[i-k+1]=que.front();
// cout<<i-k+1<<" "<<arr[i-k+1]<<endl;
}
int ret=0x3f3f3f3f;
for(int i=0,j=k+1;j<flowers.size();i++,j++)
{
int maxi=max(position[i],position[j]);
// cout<<i<<" "<<j<<" "<<position[arr[i+1]]<<" "<<arr[i+1]<<" "<<maxi<<endl;
if(position[arr[i+1]]>maxi)
{
ret=min(ret,maxi);
}
}
if(ret==0x3f3f3f3f)
{
return -1;
}
return ret;
}
};