3无重复字符的最长字串
题目:给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。
示例 1: 输入: s = "abcabcbb",输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。注意 "bca" 和 "cab" 也是正确答案。
java
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> set=new HashSet<>();
int left=0;
int maxlen=0;
for(int right=0;right<s.length();right++){
char c=s.charAt(right);
while(set.contains(c)){
set.remove(s.charAt(left));
left++;
}
set.add(c);
maxlen=Math.max(maxlen,right-left+1);
}
return maxlen;
}
}
注意是while:
例如,在字符串 "abcba" 中,当右指针指向第二个 'b' 时,窗口内是 "abc"(假设 left=0, right=3)。此时 HashSet 中有 {a, b, c},新字符 'b' 重复。我们开始 while 循环:
第一次移除 s[left] 即 'a',left 变为 1,HashSet 变为 {b, c},此时 'b' 仍然在集合中。第二次继续循环,移除 s[left] 即 'b',left 变为 2,HashSet 变为 {c},此时 'b' 不再重复,循环结束。可见,我们需要多次移除才能把旧的 'b' 赶出窗口。如果只用 if,只移除一次是不够的。
滑动窗口的模板:
java
//外层循环扩展右边界,内层循环扩展左边界
for (int l = 0, r = 0 ; r < n ; r++) {
//当前考虑的元素
while (l <= r && check()) {//区间[left,right]不符合题意
//扩展左边界
}
//区间[left,right]符合题意,统计相关信息
}
438找到字符串中所有字母异位词
题目:给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
示例 1:输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
java
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> result=new ArrayList<>();
int slen=s.length();
int plen=p.length();
if(slen<plen) return result;
int[] pcount=new int[26]; // 统计 p 中每个字符的出现次数
for(char c:p.toCharArray()){
pcount[c-'a']++;
}
int[] window=new int[26]; // 初始化窗口
for(int i=0;i<plen;i++){
window[s.charAt(i)-'a']++;
}
if(Arrays.equals(pcount,window)){
result.add(0);
}
for(int i=plen;i<slen;i++){ //开始移动窗口
char left=s.charAt(i-plen);
window[left-'a']--; // 移出左边字符
char right=s.charAt(i);
window[right-'a']++; // 加入右边字符
if (Arrays.equals(pcount, window)) { // 比较窗口与 p 的字符计数
result.add(i - plen + 1);
}
}
return result;
}
}