[LeetCode] 727. Minimum Window Subsequence 最小窗口子序列
Given strings S
and T
, find the minimum (contiguous) substring W
of S
, so that T
is a subsequenceof W
.
If there is no such window in S
that covers all characters in T
, return the empty string ""
. If there are multiple such minimum-length windows, return the one with the left-most starting index.
Example 1:
Input:
S = "abcdebdde", T = "bde"
Output: "bcde"
Explanation:
"bcde" is the answer because it occurs before "bdde" which has the same length.
"deb" is not a smaller window because the elements of T in the window must occur in order.
Note:
- All the strings in the input will only contain lowercase letters.
- The length of
S
will be in the range[1, 20000]
. - The length of
T
will be in the range[1, 100]
.
给定字符串S和T,在S中寻找最小连续子串W,使得T是W的子序列。如果没有找到返回"",如果找到多个最小长度的子串,返回左 index 最小的。
解法1:暴力搜索brute force,对于每一个s[i],从s[0]到s[i]扫描,看是否按顺序满足目标字符。 显然要超时,不是题目要求的。
解法2: 动态规划DP, 二维数组dp[i][j]表示T[0...i]在S中找到的起始下标index,使得S[index, j]满足目前T[0...i]。首先找到能满足满足T中第一个字符T[0]的S中的字符下标存入dp[0][j],也就是满足第一个字符要求一定是从这些找到的字符开始的。然后在开始找第二个字符T[1],扫到的字符dp[j]存有index,说明可以从这里记录的index开始,找到等于T[1]的S[j]就把之前那个index存进来,说明从这个index到j满足T[0..1],一直循环,直到T中的i个字符找完。如果此时dp[i][j]中有index,说明S[index, j]满足条件,如有多个输出最先找到的。
State: dp[i][j],表示在S中找到的起始下标 index ,使得 S[index...j] 满足目前 T[0...i] 是其子序列。
function: dp[i+1][k] = dp[i][j] if S[k] = T[i+1] , 如果查看到第i+1行(也就是第 T[i+1] 的字符),如果满足S[k] = T[i+1],就把上一行找到的index赋给它。
Initialize: dp[0][j] = j if S[j] = T[0] , 二维数组的第一行,如果字符S[j] = T[0], 就把S[j]的index(就是j)付给它。其他元素均为 None 或者 -1。
Return: dp[len(T) - 1][j], if dp[len(T) - 1][j] != None, 返回最小的。如果没有返回 ""
由于我们只用到前一行的值,所以可以只用2行的二维数组,每一个循环更新其中的一行。可以用 j % 2 来往复使用。
Java:
class Solution {
public String minWindow(String S, String T) {
int m = T.length(), n = S.length();
int[][] dp = new int[m + 1][n + 1];
for (int j = 0; j <= n; j++) {
dp[0][j] = j + 1;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (T.charAt(i - 1) == S.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = dp[i][j - 1];
}
}
} int start = 0, len = n + 1;
for (int j = 1; j <= n; j++) {
if (dp[m][j] != 0) {
if (j - dp[m][j] + 1 < len) {
start = dp[m][j] - 1;
len = j - dp[m][j] + 1;
}
}
}
return len == n + 1 ? "" : S.substring(start, start + len);
}
}
Java: brute force, Time O(s*t), Space O(s*t)
class Solution {
public String minWindow(String S, String T) {
int min = -1, idx = -1;
char[] Tc = T.toCharArray();
char[] Sc = S.toCharArray();
for(int i = 0;i < S.length();i++){
if(Sc[i] != Tc[0]) continue;
int len = check(Tc,Sc,i);
if(len <= 0) break;
if(min == -1 || len < min){
idx = i;
min = len;
}
}
if(min == -1) return "";
return S.substring(idx, idx + min);
} public int check(char[] Tc, char[] Sc, int start){
int i = start, j = 0;
while(i < Sc.length && j < Tc.length){
if(Sc[i] == Tc[j]) j++;
i++;
}
if(j == Tc.length) return i - start; return -1;
}
}
Java: DP, Time O(s*t), Space O(s*2)
class Solution {
public String minWindow(String S, String T) {
int[][] dp = new int[2][S.length()]; for (int i = 0; i < S.length(); ++i)
dp[0][i] = S.charAt(i) == T.charAt(0) ? i : -1; for (int j = 1; j < T.length(); ++j) {
int last = -1;
Arrays.fill(dp[j & 1], -1);
for (int i = 0; i < S.length(); ++i) {
if (last >= 0 && S.charAt(i) == T.charAt(j))
dp[j & 1][i] = last;
if (dp[j & 1][i] >= 0)
last = dp[j & 1][i];
}
} int start = 0, end = S.length();
for (int e = 0; e < S.length(); ++e) {
int s = dp[T.length() & 1][e];
if (s >= 0 && e - s < end - start) {
start = s;
end = e;
}
}
return end < S.length() ? S.substring(start, end+1) : "";
}
}
Java: Time O(s*t), Space O(s*t)
class Solution {
public String minWindow(String S, String T) {
int[][] dp = new int[T.length()][S.length()];
for(int i = 0; i < T.length(); i++) {
for(int j = 0; j < S.length(); j++) {
dp[i][j] = -1;
}
} for(int j = 0; j < S.length(); j++) {
dp[0][j] = (S.charAt(j) == T.charAt(0)) ? j : -1;
} for(int i = 1; i < T.length(); i++) {
int last = -1;
for(int j = 0; j < S.length(); j++) {
if(last >= 0 && S.charAt(j) == T.charAt(i)) {
dp[i][j] = last;
}
if(dp[i - 1][j] >= 0) {
last = dp[i - 1][j];
}
}
} int start = -1;
int length = Integer.MAX_VALUE; for(int j = 0; j < S.length(); j++) {
if(dp[T.length() - 1][j] >= 0 && (j - dp[T.length() - 1][j] + 1 < length)) {
start = dp[T.length() - 1][j];
length = j - dp[T.length() - 1][j] + 1;
}
} return (start == -1) ? "" : S.substring(start, start + length);
}
}
Python: Time O(s*t), Space O(s*2)
class Solution(object):
def minWindow(self, S, T):
dp = [[None for _ in xrange(len(S))] for _ in xrange(2)]
for j, c in enumerate(S):
if c == T[0]:
dp[0][j] = j for i in xrange(1, len(T)):
prev = None
dp[i%2] = [None] * len(S)
for j, c in enumerate(S):
if prev is not None and c == T[i]:
dp[i%2][j] = prev
if dp[(i-1)%2][j] is not None:
prev = dp[(i-1)%2][j] start, end = 0, len(S)
for j, i in enumerate(dp[(len(T)-1)%2]):
if i >= 0 and j-i < end-start:
start, end = i, j
return S[start:end+1] if end < len(S) else ""
Python:
class Solution(object):
def minWindow(self, S, T):
"""
:type S: str
:type T: str
:rtype: str
"""
ans = ''
ls, lt = len(S), len(T)
dp = [-1] * lt
for x in range(ls):
for y in range(lt - 1, -1, -1):
if T[y] == S[x]:
dp[y] = dp[y - 1] if y else x
if y == lt - 1 and dp[-1] > -1:
nlen = x - dp[-1] + 1
if not ans or nlen < len(ans):
ans = S[dp[-1] : x+1]
return ans
C++:
/*
* At time j, for each position e in S (e for end), let's remember
* the largest index cur[e] = s (for start) so that S[s: e+1] has
* T[:j+1] as a subsequence, and -1 otherwise if it isn't possible.
*/
class Solution {
public:
string minWindow(string S, string T) {
int sn = S.size(), tn = T.size();
vector<int> memo(sn, -1); for (int i = 0; i < sn; ++i) {
if (T[0] == S[i]) {
memo[i] = i;
}
} for (int j = 1; j < tn; ++j) {
vector<int> swap(sn, -1);
int currStart = -1; for (int i = 0; i < sn; ++i) {
if (S[i] == T[j] && currStart >= 0) { // T[:j+1] found
swap[i] = currStart;
} if (memo[i] >= 0) {
currStart = memo[i];
}
}
std::swap(memo, swap);
} int BAR = sn + 1, minLen = BAR;
int start = 0; for (int e = 0; e < sn; ++e){
if (memo[e] >= 0) {
int currLen = e + 1 - memo[e];
if (currLen < minLen) {
start = memo[e];
minLen = currLen;
}
}
}
return minLen == BAR ? "" : S.substr(start, minLen);
}
};
C++:
class Solution {
public:
string minWindow(string s, string t) {
int ns = s.size(), nt= t.size();
int dp[ns+1][nt+1] = {};
const int mxx = ns + 1;
//for(int i=0;i<=ns;i++) dp[i][0]=i; for (int i = 0 ; i <= ns; ++i) {
for (int j = 1; j <= nt; ++j) {
dp[i][j] = mxx;
if (i) {
dp[i][j] = min(dp[i][j], 1 + dp[i-1][j]);
if (s[i-1] == t[j-1]) dp[i][j] = min(dp[i][j], 1 + dp[i-1][j-1]);
}
}
} int ans = ns + 1, x = -1;
for (int i = 0; i <=ns; ++i)
if (dp[i][nt] < ans) {
x = i;
ans = dp[i][nt];
} if (x < 0) return "";
return s.substr(x-ans,ans);
}
};
类似题目:
[LeetCode] 3.Longest Substring Without Repeating Characters 最长无重复子串
[LeetCode] 76. Minimum Window Substring 最小窗口子串
All LeetCode Questions List 题目汇总
[LeetCode] 727. Minimum Window Subsequence 最小窗口子序列的更多相关文章
- [LeetCode] 727. Minimum Window Subsequence 最小窗口序列
Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequence of ...
- [LeetCode] Minimum Window Subsequence 最小窗口序列
Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequence of ...
- [LeetCode] 76. Minimum Window Substring 最小窗口子串
Given a string S and a string T, find the minimum window in S which will contain all the characters ...
- LeetCode——727.Minimum Window Subsequence
一.题目链接:https://leetcode.com/problems/minimum-window-substring/ 二.题目大意: 给定两个字符串S和T,要求从S中找出包含T中所有字母的最短 ...
- [LeetCode] Minimum Window Substring 最小窗口子串
Given a string S and a string T, find the minimum window in S which will contain all the characters ...
- LC 727. Minimum Window Subsequence 【lock,hard】
Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequenceof ...
- [leetcode]76. Minimum Window Substring最小字符串窗口
Given a string S and a string T, find the minimum window in S which will contain all the characters ...
- [LeetCode] 239. Sliding Window Maximum 滑动窗口最大值
Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...
- [Leetcode] minimum window substring 最小字符窗口
Given a string S and a string T, find the minimum window in S which will contain all the characters ...
随机推荐
- 史上最完整promise源码手写实现
史上最完整的promise源码实现,哈哈,之所以用这个标题,是因为开始用的标题<手写promise源码>不被收录 promise自我介绍 promise : "君子一诺千金,承诺 ...
- 编程小白入门分享三:Spring AOP统一异常处理
Spring AOP统一异常处理 简介 在Controller层,Service层,可能会有很多的try catch代码块.这将会严重影响代码的可读性."美观性".怎样才可以把更多 ...
- VS2012 VS2010 VTK引入设置
1.C/C++ ---> 附加包含的目录 F:/VTK61/VTK-6.1.0/SLN/Filters/Sources F:/VTK61/VTK-6.1.0/VTK-6.1.0/Filters/ ...
- apache commons-configuration包读取配置文件
1.pom依赖添加 <!-- 配置文件读取 --> <dependency> <groupId>commons-configuration</groupId& ...
- ubuntu18.04 + python3 安装pip3
最近在学习python 网络爬虫,正好接触到python的requests模块 我的开发环境是ubuntu18.04+python3,这个系统是默认自带了python3,且版本是python 3.6. ...
- HDU - 5513 Efficient Tree(轮廓线DP)
前言 最近学了基于连通性的状压DP,也就是插头DP,写了几道题,发现这DP实质上就是状压+分类讨论,轮廓线什么的也特别的神奇.下面这题把我WA到死- HDU-5531 Efficient Tree 给 ...
- Python 3.6 抓取微博m站数据
Python 3.6 抓取微博m站数据 2019.05.01 更新内容 containerid 可以通过 "107603" + user_id 组装得到,无需请求个人信息获取: 优 ...
- [CSS] prefers-reduced-motion
The prefers-reduced-motion CSS media feature is used to detect if the user has requested that the sy ...
- 洛谷 P1226 【模板】快速幂||取余运算 题解
Analysis 快速幂模板,注意在最后输出时也要取模. 快速幂模板 inline ll ksm(ll x,ll y) { ll ans=; ) { ) { ans*=x; ans%=k; } x*= ...
- cjss 像编写css 一样开发web应用
cjss 提供了使用类似css 的方式编写web 应用 cjss 包含的阶段 data prepare body element 几点说明 并不是所以阶段必须使用,但是每个级别只能存在一个script ...