适用的范围:
输入是数组或者字符串,求解的结果是题目要求的子数组或者子字符串。(子数组或者子字符串必须是连续的。!!!!!)
注意点:
例题:
Leetcode003无重复字符的最长字串:
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/submissions/
y总解法:
思路见:https://www.acwing.com/problem/content/801/
class Solution {
public:
int lengthOfLongestSubstring(string s) {
//存储每一个字符在[j,i]区间里出现的次数
unordered_map<char,int> heap;
int res=0;
int l=s.length();
for(int i=0,j=0;i<l;i++ ){
//加入一个新的字符s[i],出现次数+1
heap[s[i]]++;
//加入的数已经出现过一次了,从j开始一直删(heap[s[j]--])
//直到把重复的那个字符(即这次我们加入的字符=>s[i])给删了(即heap[s[i]==0]),j就停
while(j<=i&&heap[s[i]]>1){
heap[s[j]]--;
j++;
}
res=max(res,i-j+1);
}
return res;
}
};
题解:
代码:
java版(较麻烦)
public int lengthOfLongestSubstring(String s) {
//总体思路: 用哈希表保存当前滑动窗口窗口的元素(保存每个元素索引)。
// 如果窗口右边界指向的元素已经在哈希表中,则将窗口的起点重置为哈希表中重复元素的下一个位置
// 每一次迭代都通过max函数比较选出滑动窗口的最大长度。
Map<Character,Integer> map=new HashMap<>();
//创建一个Map集合,key用来存储字母,value用来存储字母的下标
int left=0;int right=0;//分别代表窗口的左右边界
int max=0;//最大不重复字串的长度。
for(right=0;right<s.length();right++){
//先判断右边界的字母是否重复,决定左边界要不要动
char t=s.charAt(right);//把右边界的字母提取出来
if(map.containsKey(t))
{
left=Math.max(map.get(t)+1,left );
//问题一:
//为什么要将窗口的起点重置为哈希表中重复元素的下一个索引,而不是起点++呢?
// 我们知道假如起点的位置<=重复元素的位置,那么此时[left,right]区间里面是一定还有重复元素的。
//只是重复++,其实只是在浪费时间,还不如直接跳到对应位置。
//问题二:
//为什么不直接取left=map.get(t)+1,而采用left=Math.max(map.get(t)+1,left );
//这段代码是用来规避哈希表查询到在滑动窗口左边的重复字符的。
// 例如,在"tmmzuxt"这个字符串中,遍历到最后一步时,最后一个字符't'和第一个字符't'是相等的。
// 如果没有max函数锁定住滑动窗口的左边界,left就会变为第一个t的位置+1,
//最后输出的最长无重复子串会变成"mmzuxt",这是我们不希望看到的。
}
max=Math.max(right-left+1,max);
map.put(t,right);
}
return max;
Leetcode053:
描述:
地址:
具体可以看我写的文章,这里就不再写一遍了。