stan

share everything

leetcode727



最小窗口子序列

题目描述:

给定字符串 s1s2,找出 s1 中最短的连续 子串,使得 s2 是该子串的 子序列

如果 s1 中没有窗口可以包含 s2 中的所有字符,返回空字符串 ""。如果有不止一个最短长度的窗口,返回 开始位置最靠左 的那个。

示例 1:

1
2
3
4
5
6
输入:
s1 = "abcdebdde", s2 = "bde"
输出:"bcde"
解释:
"bcde" 是答案,因为它在相同长度的字符串 "bdde" 出现之前。
"deb" 不是一个更短的答案,因为在窗口中必须按顺序出现 T 中的元素。

示例 2:

1
2
输入:s1 = "jmeqksfrsdcmsiwvaovztaqenprpvnbstl", s2 = "u"
输出:""

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public String minWindow(String s1, String s2) {
int l1 = s1.length(), l2 = s2.length();
int p1 = 0, p2 = 0;
int min = l1 + 1;
String res = "";
while (p1 < l1) {
if (s1.charAt(p1) == s2.charAt(p2)) {
p2++;
}
if (p2 == l2) {
int r = p1;
while (p2 > 0) {
if (s1.charAt(p1) == s2.charAt(p2 - 1)) {
p2--;
}
p1--;
}
p1++;
if (r - p1 + 1 < min) {
min = r - p1 + 1;
res = s1.substring(p1, r + 1);
}
}
p1++;
}
return res;
}
}

思路 :

用滑动窗口去做,遍历s1串,如果s2到了末尾(p2 == l2),进行回溯寻找起点。

几个注意点:

i. 因为先做p2++,所以末尾的判断条件是 p2 == l2, 而不是p2 == l2 - 1,此时p1还没加1,还在最后一个字符位置。

ii. 进行回溯后,p1指向的位置是第一个字符的前一个位置,所以要加1。

iii. 要维护一个min变量,判断这个长度是不是最小的,如果是,就动态更新res的值。

iv. 因为p1的坐标进行了回溯,最后又加1了,所以下一次遍历是从s1的下一个字符开始的。s1确实需要进行遍历,因为要找到最小的子串。