Java 求解最小覆盖子串
Posted 南淮北安
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 求解最小覆盖子串相关的知识,希望对你有一定的参考价值。
一、题目
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
- 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
- 如果 s 中存在这样的子串,我们保证它是唯一的答案。
二、题解
采用滑动窗口的思想
用i,j表示滑动窗口的左边界和右边界,通过改变i,j来扩展和收缩滑动窗口,可以想象成一个窗口在字符串上游走,当这个窗口包含的元素满足条件,即包含字符串T的所有元素,记录下这个滑动窗口的长度j-i+1,这些长度中的最小值就是要求的结果。
- 不断增加j使滑动窗口增大,直到窗口包含了T的所有元素
- 不断增加i使滑动窗口缩小,因为是要求最小字串,所以将不必要的元素排除在外,使长度减小,直到碰到一个必须包含的元素,这个时候不能再扔了,再扔就不满足条件了,记录此时滑动窗口的长度,并保存最小值
- 让i再增加一个位置,这个时候滑动窗口肯定不满足条件了,那么继续从步骤一开始执行,寻找新的满足条件的滑动窗口,如此反复,直到j超出了字符串S范围。
需要一个数组维护当前滑动窗口需要的各元素数量
三、代码
class Solution
public String minWindow(String s, String t)
//ASCII字符的范围最大到127
int[] chars = new int[128];
//记录需要的字符个数
for (char ch : t.toCharArray())
chars[ch]++;
//left滑动窗口左边界
//start记录最小的窗口起始下标
//count记录窗口还需要多少字符满足条件
int left = 0, start = 0, size = Integer.MAX_VALUE, count = t.length();
//遍历所有字符
for (int right = 0; right < s.length(); right++)
char ch = s.charAt(right);
if (chars[ch] > 0)
count--;
chars[ch]--;
//窗口包含所有字符
if (count == 0)
//开始收缩窗口
while (right > left && chars[s.charAt(left)] < 0)
chars[s.charAt(left)]++;
left++;
if (size > right - left + 1)
size = right - left + 1;
start = left;
//窗口左移
chars[s.charAt(left)]++;
left++;
count++;
return size == Integer.MAX_VALUE ? "" : s.substring(start, start + size);
四、总结
left 和 right 都会扫描一遍 字符串 S,最多扫描两次,所以时间复杂度为
O
(
n
)
O(n)
O(n),空间复杂度为
O
(
k
)
O(k)
O(k),
k 为 S 和 T 中字符的集合
以上是关于Java 求解最小覆盖子串的主要内容,如果未能解决你的问题,请参考以下文章