【算法】滑动窗口题单——3.不定长滑动窗口(求最短/最小)⭐ 删除最短的子数组使剩余数组有序

news/2024/5/20 7:26:26 标签: 算法, 滑动窗口, 子数组, 双指针

文章目录

  • 209. 长度最小的子数组
  • 1234. 替换子串得到平衡字符串
  • 1574. 删除最短的子数组使剩余数组有序⭐
    • 枚举左端点,移动右端点
    • 枚举右端点,移动左端点
  • 76. 最小覆盖子串

题单来源:https://leetcode.cn/problems/minimum-size-subarray-in-infinite-array/solutions/2464878/hua-dong-chuang-kou-on-shi-jian-o1-kong-cqawc/

209. 长度最小的子数组

https://leetcode.cn/problems/minimum-size-subarray-sum/description/

在这里插入图片描述

提示:

1 <= target <= 10^9
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^5

进阶:

如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

O(n)滑动窗口

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length, ans = n + 1, s = 0;
        for (int l = 0, r = 0; r < n; ++r) {
            s += nums[r];
            while (s - nums[l] >= target) s -= nums[l++];
            if (s >= target) ans = Math.min(ans, r - l + 1);
        }
        return ans == n + 1? 0: ans;
    }
}

O(nlogn) 前缀和+二分查找

枚举左端点,二分查找右端点。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length, ans = n + 1;
        int[] s = new int[n + 1];
        for (int i = 1; i <= n; ++i) s[i] = s[i - 1] + nums[i - 1];
        for (int i = 0; i < n; ++i) {
            int l = i, r = n, t = target + s[i];
            while (l < r) {
                int mid = l + r >> 1;
                if (s[mid] >= t) r = mid;
                else l = mid + 1;
            }
            if (s[l] >= t) ans = Math.min(ans, l - i);
        }
        return ans == n + 1? 0: ans;
    }
}

1234. 替换子串得到平衡字符串

https://leetcode.cn/problems/replace-the-substring-for-balanced-string/description/

在这里插入图片描述

提示:

1 <= s.length <= 10^5
s.length 是 4 的倍数
s 中只含有 'Q', 'W', 'E', 'R' 四种字符

需要满足的条件是窗口外的各个元素的数量都<=n/4,这样就可以完成替换。

class Solution {
    public int balancedString(String s) {
        int n = s.length(), ans = n;
        int[] cnt = new int[128];
        for (char ch: s.toCharArray()) cnt[ch]++;
        for (int l = 0, r = 0; l < n; ++l) {
            while (!check(cnt, n / 4) && r < n) --cnt[s.charAt(r++)];
            if (check(cnt, n / 4)) ans = Math.min(ans, r - l);
            ++cnt[s.charAt(l)];
        }
        return ans;
    }

    public boolean check(int[] cnt, int x) {
        return cnt['Q'] <= x && cnt['W'] <= x && cnt['E'] <= x && cnt['R'] <= x;
    }
}

1574. 删除最短的子数组使剩余数组有序⭐

https://leetcode.cn/problems/shortest-subarray-to-be-removed-to-make-array-sorted/description/

在这里插入图片描述

提示:

1 <= arr.length <= 10^5
0 <= arr[i] <= 10^9

定义好 l 和 r 的含义,分别是第一个非递减子数组的结束位置和第二个非递减子数组的开始位置,而不是中间被删除的子数组的两端。

枚举左端点,移动右端点

class Solution {
    public int findLengthOfShortestSubarray(int[] arr) {
        int n = arr.length, r = n - 1;      // r表示下一个非递减数组的开始位置
        while (r > 0 && arr[r - 1] <= arr[r]) r--;
        if (r == 0) return 0;
        int ans = r;
        // l表示第一个非递减数组的结束位置
        for (int l = 0; l == 0 || arr[l - 1] <= arr[l]; ++l) {
            while (r < n && arr[r] < arr[l]) ++r;
            ans = Math.min(ans, r - l - 1);
        }
        return ans;
    }
}

枚举右端点,移动左端点

class Solution {
    public int findLengthOfShortestSubarray(int[] arr) {
        int n = arr.length, l = 0;      // l表示第一个非递减数组的结束位置
        while (l + 1 < n && arr[l + 1] >= arr[l]) l++;
        if (l == n - 1) return 0;
        int ans = n - l - 1;
        // r表示下一个非递减数组的开始位置
        for (int r = n - 1; r == n - 1 || arr[r] <= arr[r + 1]; --r) {
            while (l >= 0 && arr[l] > arr[r]) l--;
            ans = Math.min(ans, r - l - 1);
        }
        return ans;
    }
}

76. 最小覆盖子串

https://leetcode.cn/problems/minimum-window-substring/description/

在这里插入图片描述

提示:

m == s.length
n == t.length
1 <= m, n <= 10^5
s 和 t 由英文字母组成

进阶:你能设计一个在 o(m+n) 时间内解决此问题的算法吗?

维护窗口中的字符出现数量。
枚举右端点,根据条件收缩左端点即可。

class Solution {
    int[] cnt1 = new int[128], cnt2 = new int[128];

    public String minWindow(String s, String t) {
        for (char ch: t.toCharArray()) cnt2[ch]++;
        String ans = "";
        int mnL = s.length() + 1;
        for (int l = 0, r = 0; r < s.length(); ++r) {
            cnt1[s.charAt(r)]++;
            while (l < r && cnt1[s.charAt(l)] > cnt2[s.charAt(l)]) cnt1[s.charAt(l++)]--;
            if (check() && mnL > r - l + 1) {
                mnL = r - l + 1;
                ans = s.substring(l, r + 1);
            }
        }
        return ans;
    }

    public boolean check() {
        for (int i = 0; i < 128; ++i) {
            if (cnt1[i] < cnt2[i]) return false;
        }
        return true;
    }
}

http://www.niftyadmin.cn/n/5129200.html

相关文章

LrC 13 ACR 16:镜头模糊

的Adobe Lightroom Classic 13 &#xff08; 2023 年 10 月版&#xff09;及 Adobe Camera Raw 16 新增的镜头模糊 Lens Blur功能可以基于 AI 技术生成深度图&#xff0c;并依据深度图对图像添加模糊和焦外成像&#xff08;散景光斑&#xff09;效果。 LrC&#xff1a;修改照片…

演讲比赛常见误区及解决方法

演讲比赛常见误区及解决方法 一、演讲内容选择错误 1. 主题选择不合理 许多参赛者选择的主题内容&#xff0c;与比赛题目要求或听众背景不符&#xff0c;难以引起听众的兴趣。正确选择主题应考虑以下几点&#xff1a; - 主题应与比赛题目要求相符合&#xff0c;切合比赛定位…

Spring Cloud Gateway + Knife4j 4.3 实现微服务网关聚合接口文档

目录 前言Spring Cloud 整合 Knife4jpom.xmlapplication.ymlSwaggerConfig.java访问单服务接口文档 Spring Cloud Gateway 网关聚合pom.xmlapplication.yml访问网关聚合接口文档 接口测试**登录认证**获取登录用户信息 结语源码 前言 youlai-mall 开源微服务商城新版本基于 Sp…

Android S从桌面点击图标启动APP流程 (五)

系列文章 Android S从桌面点击图标启动APP流程 (一)Android S从桌面点击图标启动APP流程 (二) Android S从桌面点击图标启动APP流程 (三) Android S从桌面点击图标启动APP流程 (四) Android S从桌面点击图标启动APP流程 (五) Android S从桌面点击图标启动APP流程 (六) An…

linux,windows命令行输出控制指令,带颜色的信息,多行刷新,进度条效果,golang

一、带颜色的信息 linux 颜色及模式编号 // 前景 背景 颜色 // --------------------------------------- // 30 40 黑色 // 31 41 红色 // 32 42 绿色 // 33 43 黄色 // 34 44 蓝色 // 35 45 紫红色 // 36 46 青蓝色 // 37 47 白色 // // 模式代码 意义 //…

【机器学习】集成学习Boosting

文章目录 集成学习BoostingAdaBoost梯度提升树GBDTXGBoostxgboost库sklearn APIxgboost库xgboost应用 集成学习 集成学习&#xff08;ensemble learning&#xff09;的算法主要包括三大类&#xff1a;装袋法&#xff08;Bagging&#xff09;&#xff0c;提升法&#xff08;Boo…

TSINGSEE青犀智慧仓储可视化视频智能监管系统方案

一、背景与需求 对于现在很多大型工厂或者物流基地来说&#xff0c;仓库无疑是存放物品的重点场所。仓储存放着大量货物&#xff0c;同时存在大量的辅助设备&#xff0c;需要进行全方位的监管&#xff0c;以避免发生安全事故&#xff0c;造成财产损失。原有的人工巡检方式已无…

子集生成算法:给定一个集合,枚举所有可能的子集

给定一个集合&#xff0c;枚举所有可能的子集。 &#xff08;为简单起见&#xff0c;本文讨论的集合中没有重复元素&#xff09; 1、方法一&#xff1a;增量构造法 第一种思路是一次选出一个元素放到集合中&#xff0c;程序如下&#xff1a; void print_subset(int n, int …