单调队列适合维护区间的最值问题
入队操作
队尾入队,会把之前破坏单调性的元素都从队尾移出(维护单调性)
出队操作
如果队首元素超出区间范围,就将元素从队首出队
元素性质
队首元素,永远是当前维护区间的(最大/最小)值
int main(){
int n, k;
vector<int> arr;
cin >> n >> k;
for(int i = 0, a; i < n; i++){
cin >> a;
arr.push_back(a);
}
deque<int> q;
for(int i = 0; i < n; i++){
while(q.size() && arr[q.back()] > arr[i]) q.pop_back();
q.push_back(i);
if(i - q.front() == k) q.pop_front();
if(i + 1 < k) continue;
if(i + 1 > k) cout << " ";
cout << arr[q.fornt()];
}
return 0;
}
239. 滑动窗口最大值
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> q;
vector<int> ret;
for(int i = 0;i < nums.size(); i++){
while(q.size() && nums[q.back()] < nums[i]) q.pop_back();
q.push_back(i);
if(i - q.front() == k) q.pop_front();
if(i + 1 < k) continue;
ret.push_back(nums[q.front()]);
}
return ret;
}
};
862. 和至少为 K 的最短子数组
class Solution {
public:
int shortestSubarray(vector<int>& nums, int k) {
deque<int> q;
vector<long> sum(nums.size() + 1);
sum[0] = 0;
for(int i = 0; i < nums.size(); i++) sum[i + 1] = sum[i] + nums[i];
q.push_back(0);
int pos = -1, ans = -1;
for(int i = 1; i < sum.size(); i++){
while(q.size() && sum[i] - sum[q.front()] >= k){
pos = q.front();
q.pop_front();
}
if(pos != -1 && (i - pos < ans || ans == -1)) ans = i - pos;
while(q.size() && sum[i] < sum[q.back()]) q.pop_back();
q.push_back(i);
}
return ans;
}
};
1438. 绝对差不超过限制的最长连续子数组
class Solution {
public:
int max_k, val;
void dfs(TreeNode *root, int k){
if(root == nullptr) return;
if(k > max_k){
max_k = k, val = root->val;
}
dfs(root->left, k + 1);
dfs(root->right, k + 1);
}
int findBottomLeftValue(TreeNode* root) {
max_k = -1, val = 0;
dfs(root, 0);
return val;
}
};
135. 分发糖果
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> l(ratings.size()), r(ratings.size());
for(int i = 0, j = 1; i < l.size(); i++){
if(i && ratings[i] > ratings[i - 1]) j += 1;
else j = 1;
l[i] = j;
}
for(int i = r.size() - 1, j = 1; i >= 0; i--){
if(i < r.size() - 1 && ratings[i] > ratings[i + 1]) j += 1;
else j = 1;
r[i] = j;
}
int ans = 0;
for(int i = 0; i < l.size(); i++) ans += max(l[i], r[i]);
return ans;
}
};
365. 水壶问题
class Solution {
public:
typedef pair<int, int> PII;
PII getNext(int k, int x, int X, int y, int Y){
switch(k){
case 0: return PII(0, y);
case 1: return PII(x, 0);
case 2: {
int delta = min(x, Y - y);
return PII(x - delta, y + delta);
}
case 3: {
int delta = min(X - x, y);
return PII(x + delta, y - delta);
}
case 4: return PII(X, y);
case 5: return PII(x, Y);
}
return PII(0, 0);
}
struct HASH {
long long operator()(const PII &a) const {
return ((long long)(a.first) << 31) + a.second;
}
};
bool canMeasureWater(int jug1Capacity, int jug2Capacity, int targetCapacity) {
unordered_set<PII, HASH> vis;
queue<PII> q;
vis.insert(PII(0, 0));
q.push(PII(0, 0));
while(!q.empty()){
PII cur = q.front();
if(cur.first + cur.second == targetCapacity) return true;
q.pop();
for(int i = 0; i < 6; i++){
PII temp = getNext(i, cur.first, jug1Capacity, cur.second ,jug2Capacity);
if(vis.find(temp) != vis.end()) continue;
vis.insert(temp);
q.push(temp);
}
}
return false;
}
};
1760. 袋子里最少数目的球
class Solution {
public:
int f(vector<int> &nums, int x){
int cnt = 0;
for(int i = 0; i < nums.size(); i++){
cnt += nums[i] / x + !!(nums[i] % x) - 1;
}
return cnt;
}
int bs(vector<int> &nums, int l, int r, int n){
if(l == r) return l;
int mid = (l + r) >> 1;
if(f(nums, mid) <= n) r= mid;
else l = mid + 1;
return bs(nums, l, r, n);
}
int minimumSize(vector<int>& nums, int maxOperations) {
int l = 1, r;
for(auto x: nums) r= max(r, x);
return bs(nums, l, r, maxOperations);
}
};
45. 跳跃游戏 II
class Solution {
public:
int jump(vector<int>& nums) {
if(nums.size() <= 1) return 0;
int pre = 1, pos = nums[0], cnt = 1;
while(pos + 1 < nums.size()){
int j = pre;
for(int i = pre + 1; i <= pos; i++){
if(i + nums[i] > j + nums[j]) j = i;
}
pre = pos + 1, pos = j + nums[j];
cnt += 1;
}
return cnt;
}
};
93. 复原 IP 地址
class Solution {
public:
void dfs(string &s, int k, int ind, vector<string> &ret){
if(ind >= s.size()) return;
if(k == 4){
int num = 0;
if(s.size() - ind > 1 && s[ind] == '0') return;
for(int i = ind; i < s.size(); i++){
num = num * 10 + s[i] - '0';
if(num > 255) return;
}
ret.push_back(s);
}
for(int i = ind, num = 0; i < s.size(); i++){
num = num * 10 + s[i] - '0';
if(num > 255) return;
if(i - ind >= 1 && s[ind] == '0') return;
s.insert(i + 1, ".");
dfs(s, k + 1, i + 2, ret);
s.erase(i + 1, 1);
}
}
vector<string> restoreIpAddresses(string s) {
vector<string> ret;
dfs(s, 1, 0, ret);
return ret;
}
};
46. 全排列
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> ret;
do{
ret.push_back(nums);
}while(next_permutation(nums.begin(), nums.end()));
return ret;
}
};
43. 字符串相乘
class Solution {
public:
string multiply(string num1, string num2) {
vector<int> a(num1.size()), b(num2.size()), c(a.size() + b.size() - 1);
for(int i = 0; i < num1.size(); i++) a[a.size() - i - 1] = num1[i] - '0';
for(int i = 0; i < num2.size(); i++) b[b.size() - i - 1] = num2[i] - '0';
for(int i = 0; i < a.size(); i++){
for(int j = 0; j < b.size(); j++){
c[i + j] += a[i] * b[j];
}
}
for(int i = 0; i < c.size(); i++){
if(c[i] < 10) continue;
if(i + 1 == c.size()) c.push_back(0);
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
while(c.size() > 1 && c[c.size() - 1] == 0) c.pop_back();
string ret = "";
for(int i = c.size() - 1; i >=0 ; i--) ret += c[i] + '0';
return ret;
}
};