最小覆盖子串
时间:2022-07-22
本文章向大家介绍最小覆盖子串,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
问题描述
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
解决方案
题目要求要找到包含T中所有字符的的最小子串,这里的所有字符包括重复字符,也就是说若T中含有两个‘a’,要求的S的子串中也至少含两个‘a’。因此使用一Map存储T中所有字符(key = 字符 value = 出现的次数)。
使用滑动窗口求解,left和right表示窗口的左右边界,为[left, right),其初值均为0。首先让right向右滑动,直到当前窗口中的元素可以覆盖T,然后left也向右滑动,直到不能覆盖T为止,滑动过程中存储最小的子串,如此直到right到达最后一个元素位置。
实现代码如下:
class Solution {
public String minWindow(String s, String t) {
Map<Character, Integer> sCount = new HashMap<>();
Map<Character, Integer> tCount = new HashMap<>();
char[] arr = s.toCharArray();
for(int i = 0; i < t.length(); i++){
tCount.put(t.charAt(i), tCount.getOrDefault(t.charAt(i), 0) + 1);
}
// 最小覆盖子串的长度
int length = s.length() + 1;
// 最小覆盖子串开始位置
int start = 0;
// 最小覆盖子串结束位置
int end = 0;
int left = 0;
int right = 0;
while(right < arr.length){
sCount.put(arr[right], sCount.getOrDefault(arr[right], 0) + 1);
right++;
while(process(sCount, tCount)){
if(length > right - left){
length = right - left;
start = left;
end = right;
}
sCount.put(arr[left], sCount.get(arr[left]) - 1);
left++;
}
}
return length == s.length() + 1 ? "" : s.substring(start, end);
}
// s是否可以覆盖t
public boolean process(Map<Character, Integer> sCount, Map<Character, Integer> tCount){
for(Map.Entry<Character, Integer> entry : tCount.entrySet()){
if(entry.getValue().intValue() > sCount.getOrDefault(entry.getKey(), 0).intValue()){
return false;
}
}
return true;
}
}
时间复杂度为O(N * M),其中N为s的长度,M为t的长度。首先滑动窗口滑动过程时间复杂度为O(N),每一个窗口对于当前窗口能否覆盖t的时间复杂度为O(M),因此总体时间复杂度为O(M * N)。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- CentOS 8 如何安装 htop
- Discourse 重复安装过程中的密钥签发问题
- Appium之「元素定位和UiAutomator表达式」
- 机器人软件开发:机器人开源库安装
- 2020-10-05:如何求模平方根?
- leetcode栈之比较含退格的字符串
- Discourse 如何不使用 Let’s Encrypt 而使用 CA 签名的密钥进行安装
- 3分钟短文:Laravel slug,让你的url地址更“好记”
- Qt音视频开发28-Onvif信息获取
- CentOS 8 启用 NTP 服务
- Discourse 如何使用命令行方式进行恢复
- CentOS 8 Apache 启用 SSL
- leetcode栈之二叉树的前序遍历
- 前端学数据结构与算法(七): 从零实现优先队列-堆及其应用
- 前端学数据结构与算法(六):二叉树的四种遍历方式及其应用