3.无重复字符的最长子串
class Solution {
public int lengthOfLongestSubstring(String s) {
//滑动窗口(双指针!)
int n = s.length();
Map<Character, Integer> map = new HashMap<>();
if(n == 0) return 0;
int left = 0, ans = 1;
for(int right = 0;right < n;right++){
char ch = s.charAt(right);
if(map.containsKey(ch)){
left = Math.max(map.get(ch) + 1, left);//这一步很关键!因为left更新后,map中可能有元素未更新,若不使用max,则会使left前移
}
map.put(ch, right);
ans = Math.max(right-left+1, ans);
}
return ans;
//动态规划 用了substring比较耗时
// int n = s.length(), ans = 1;
// if(n == 0) return 0;
// int[] dp = new int[n];
// dp[0] = 1;
// for(int i = 1;i < n;i++){
// if(s.substring(i-dp[i-1], i).indexOf(s.charAt(i)) == -1){//上一个最长序列不包含该字母
// dp[i] = dp[i-1] + 1;
// }
// else{
// int loc = s.substring(i-dp[i-1], i).lastIndexOf(s.charAt(i));//lastIndexOf最后依次出现的位置
// dp[i] = dp[i-1] - loc;
// }
// ans = Math.max(ans, dp[i]);
// }
// return ans;
}
}
438.找到字符串中所有字母异位词
class Solution {
public List<Integer> findAnagrams(String s, String p) {
//滑动窗口
List<Integer> ans = new ArrayList<>();
if(p.length() > s.length())
return ans;
int len = p.length();
//定义数组记录s,p中出现的字母频次(关键!)根据两数组是否相等来判断异位词!
int[] sCont = new int[26];//该数组并不是记录整个s的字母,而是每次选取len个连续字母记录!
int[] pCont = new int[26];
for(int i = 0;i < len;i++){
sCont[s.charAt(i)-'a']++;
pCont[p.charAt(i)-'a']++;
}
if(Arrays.equals(sCont, pCont))
ans.add(0);
for(int i = 1;i <= s.length()-len;i++){
sCont[s.charAt(i-1)-'a']--;
sCont[s.charAt(i+len-1)-'a']++;
if(Arrays.equals(sCont, pCont)){
ans.add(i);
}
}
return ans;
//滑动窗口+双指针
// List<Integer> ans = new ArrayList<>();
// if(p.length() > s.length())
// return ans;
// int len = p.length();
// int[] sCont = new int[26];
// int[] pCont = new int[26];
// for(int i = 0;i < len;i++){
// pCont[p.charAt(i)-'a']++;
// }
// int left = 0;
// for(int right = 0;right < s.length();right++){
// sCont[s.charAt(right)-'a']++;
// while(sCont[s.charAt(right)-'a'] > pCont[s.charAt(right)-'a']){//说明s[left--right]中有其他字母或多余字母,要将left一直左移直到去掉多余字母
// sCont[s.charAt(left)-'a']--;
// left++;
// }
// if(right-left+1 == len){
// ans.add(left);
// }
// }
// return ans;
}
}
76. 最小覆盖子串
class Solution {
public String minWindow(String s, String t) {
//滑动窗口
int sLen = s.length();
int tLen = t.length();
//维护两个数组,记录已有字符串指定字符的出现次数,和目标字符串指定字符的出现次数
//ASCII表总长128
int[] need = new int[128];
int[] have = new int[128];
//将目标字符串指定字符的出现次数记录
for (int i = 0; i < t.length(); i++) {
need[t.charAt(i)]++;
}
//初始化
int left = 0, right = 0;
int count = 0;//记录have中的need需要的字符数量
int minl = sLen+1, begin = 0;//用于记录答案
while(right < sLen){
char r = s.charAt(right);
if(need[r] == 0){//不是需要的字符
right++;
continue;
}
//一定要先判断
if(have[r] < need[r]){//如果r为被目标字符串需要,且出现的频次小于指定频次
count++;
}
have[r]++;
right++;
//窗口里的字符已经满足需求,移动left
while(count == tLen){
if(right - left < minl){//记录最小窗口
minl = right - left;
begin = left;
}
char l = s.charAt(left);
if(need[l] == 0){//l不是需要的字符
left++;
continue;
}
//一定要先判断
if(have[l] == need[l])//如果左边即将要去掉的字符被目标字符串需要,且出现的频次正好等于指定频次
count--;
have[l]--;
left++;
}
}
if(minl == sLen+1)
return "";
return s.substring(begin, begin+minl);
}
//暴力法,超时
// int len = t.length(), n = s.length();
// if(n < len)
// return "";
// Map<Character, Integer> chToNum = new HashMap<>();
// for(int i = 0;i < len;i++){
// char ch = t.charAt(i);
// chToNum.put(ch, chToNum.getOrDefault(ch, 0)+1);
// }
// Map<Character, Integer> map = new HashMap<>();
// for(int l = len;l <= n;l++){
// //初始化
// map.clear();
// for(int i = 0;i < l;i++){//当l>len时
// char ch = s.charAt(i);
// map.put(ch, map.getOrDefault(ch, 0)+1);
// }
// //滑动窗口
// for(int start = 0;start <= n-l;start++){
// if(start > 0){
// char ch1 = s.charAt(start-1), ch2 = s.charAt(start+l-1);
// map.put(ch1, map.get(ch1)-1);
// map.put(ch2, map.getOrDefault(ch2, 0)+1);
// }
// if(chToNum.size() > map.size())
// continue;
// if(f(chToNum, map))
// return s.substring(start, start+l);
// }
// }
// return "";
// }
// public boolean f(Map<Character, Integer> chToNum, Map<Character, Integer> map){
// for(Map.Entry<Character, Integer> entry : chToNum.entrySet()){
// char ch = entry.getKey();
// int num = entry.getValue();
// if(!map.containsKey(ch) || map.get(ch) < num)
// return false;
// }
// return true;
// }
}