最小 Window 子字符串我的解决方案的时间复杂度
Minimum Window Substring the time complexity of my solution
最小 Window 子字符串
这是Leetcode的一道题https://leetcode.com/problems/minimum-window-substring/
我找到了一个基于滑动 Window 算法的解决方案,但我无法计算出时间复杂度。有人说是O(N),我觉得不是。请帮助我,谢谢!
public class Solution {
// Minimum Window Algorithm, the algorithm must fit for specific problem, this problem is diff from ...words
// 348ms
public String minWindow(String s, String t) {
int N = s.length(), M = t.length(), count = 0;
String res = "";
if (N < M || M == 0) return res;
int[] lib = new int[256], cur = new int[256]; // ASCII has 256 characters
for (int i = 0; i < M; lib[t.charAt(i++)]++); // count each characters in t
for (int l = 0, r = 0; r < N; r++) {
char c = s.charAt(r);
if (lib[c] != 0) {
cur[c]++;
if (cur[c] <= lib[c]) count++;
if (count == M) {
char tmp = s.charAt(l);
while (lib[tmp] == 0 || cur[tmp] > lib[tmp]) {
cur[tmp]--;
tmp = s.charAt(++l);
}
if (res.length() == 0 || r - l + 1 < res.length())
res = s.substring(l, r + 1);
count--; // should add these three lines for the case cur[c] c is char in s but not the one visited
cur[s.charAt(l)]--;
l++;
}
}
}
return res;
}
}
将 s 中的每个字符添加到 r
位置需要 N 步
不超过O(N)个while
个运算符-至多N个工作周期++l
个操作,至多N个无价值的while
条件检查
如果我们不考虑 s.substring
,那么总体复杂度是线性的。
注意子串操作应该移出循环,我们只保留最好的索引对,并在最后得到子串。
check out my solution:
public class Solution {
public String minWindow(String S, String T) {
Map<Character, Integer> pattern = new HashMap<Character, Integer>();
Map<Character, Integer> cur = new HashMap<Character, Integer>();
Queue<Integer> queue = new LinkedList<Integer>();
int min = Integer.MAX_VALUE;
int begin = 0, end = 0;
// fill in pattern by T
for(int i = 0;i < T.length();i++) addToMap(pattern, T.charAt(i));
// initialize current set
for(int i = 0;i < T.length();i++) cur.put(T.charAt(i), 0);
// go through S to match the pattern by minimum length
for(int i = 0;i < S.length();i++){
if(pattern.containsKey(S.charAt(i))){
queue.add(i);
addToMap(cur, S.charAt(i));
// check if pattern is matched
while(isMatch(pattern, cur)){ /* Important Code! */
if(i - queue.peek() < min){
min = i - queue.peek();
begin = queue.peek();
end = i+1;
}
cur.put(S.charAt(queue.peek()), cur.get(S.charAt(queue.peek()))-1);
queue.poll();
}
}
}
return end > begin?S.substring(begin, end):"";
}
private void addToMap(Map<Character, Integer> map, Character c){
if(map.containsKey(c))
map.put(c, map.get(c)+1);
else
map.put(c,1);
}
private boolean isMatch(Map<Character, Integer> p, Map<Character, Integer> cur){
for(Map.Entry<Character, Integer> entry: p.entrySet())
if(cur.get((char)entry.getKey()) < (int)entry.getValue()) return false;
return true;
}
}
最小 Window 子字符串
这是Leetcode的一道题https://leetcode.com/problems/minimum-window-substring/
我找到了一个基于滑动 Window 算法的解决方案,但我无法计算出时间复杂度。有人说是O(N),我觉得不是。请帮助我,谢谢!
public class Solution {
// Minimum Window Algorithm, the algorithm must fit for specific problem, this problem is diff from ...words
// 348ms
public String minWindow(String s, String t) {
int N = s.length(), M = t.length(), count = 0;
String res = "";
if (N < M || M == 0) return res;
int[] lib = new int[256], cur = new int[256]; // ASCII has 256 characters
for (int i = 0; i < M; lib[t.charAt(i++)]++); // count each characters in t
for (int l = 0, r = 0; r < N; r++) {
char c = s.charAt(r);
if (lib[c] != 0) {
cur[c]++;
if (cur[c] <= lib[c]) count++;
if (count == M) {
char tmp = s.charAt(l);
while (lib[tmp] == 0 || cur[tmp] > lib[tmp]) {
cur[tmp]--;
tmp = s.charAt(++l);
}
if (res.length() == 0 || r - l + 1 < res.length())
res = s.substring(l, r + 1);
count--; // should add these three lines for the case cur[c] c is char in s but not the one visited
cur[s.charAt(l)]--;
l++;
}
}
}
return res;
}
}
将 s 中的每个字符添加到 r
位置需要 N 步
不超过O(N)个while
个运算符-至多N个工作周期++l
个操作,至多N个无价值的while
条件检查
如果我们不考虑 s.substring
,那么总体复杂度是线性的。
注意子串操作应该移出循环,我们只保留最好的索引对,并在最后得到子串。
check out my solution:
public class Solution {
public String minWindow(String S, String T) {
Map<Character, Integer> pattern = new HashMap<Character, Integer>();
Map<Character, Integer> cur = new HashMap<Character, Integer>();
Queue<Integer> queue = new LinkedList<Integer>();
int min = Integer.MAX_VALUE;
int begin = 0, end = 0;
// fill in pattern by T
for(int i = 0;i < T.length();i++) addToMap(pattern, T.charAt(i));
// initialize current set
for(int i = 0;i < T.length();i++) cur.put(T.charAt(i), 0);
// go through S to match the pattern by minimum length
for(int i = 0;i < S.length();i++){
if(pattern.containsKey(S.charAt(i))){
queue.add(i);
addToMap(cur, S.charAt(i));
// check if pattern is matched
while(isMatch(pattern, cur)){ /* Important Code! */
if(i - queue.peek() < min){
min = i - queue.peek();
begin = queue.peek();
end = i+1;
}
cur.put(S.charAt(queue.peek()), cur.get(S.charAt(queue.peek()))-1);
queue.poll();
}
}
}
return end > begin?S.substring(begin, end):"";
}
private void addToMap(Map<Character, Integer> map, Character c){
if(map.containsKey(c))
map.put(c, map.get(c)+1);
else
map.put(c,1);
}
private boolean isMatch(Map<Character, Integer> p, Map<Character, Integer> cur){
for(Map.Entry<Character, Integer> entry: p.entrySet())
if(cur.get((char)entry.getKey()) < (int)entry.getValue()) return false;
return true;
}
}