1、滑动窗口
原题:
3. 给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
题解:
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int left = 0;
for(int i = 0; i < s.length(); i ++){
if(map.containsKey(s.charAt(i))){
left = Math.max(left,map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i),i);
max = Math.max(max,i-left+1);
}
return max;
}
}
知识点:
①滑动窗口:
要理解
left = Math.max(left,map.get(s.charAt(i)) + 1);
需要回归到滑动窗口的原理上。
窗口中始终是无重复字母的字符串。 我们通过窗口的左界和右界控制窗口。
右界不用特意操作,因为它是+1,+1地涨上去,记得在循环里+1就好。
左界:每当有一个字符曾经出现过,就需要判断左界。
重点来了:
若被判断的字符上一次出现的位置就在滑动窗口内,即 [ i,j ] 内, 则需要left改变位置,改变为该字符上次出现位置+1。也就是left = map.get(s.charAt(i)) + 1
的情况。
若不在滑动窗口内,则不用管。 不用管是因为:窗口中字符串没有重复字符。窗口符合定义。所以left = left,
即这个窗口暂时不变。
②HashMap可以用来寻找重复字符
1.两数之和也用到了HashMap
③HashMap的put方法:如果插入的key对应的value已存在,则更新value值。
本题通过 map.put(s.charAt(i),i);
更新字符最新一次出现的位置。因为我们要判断字符出现的位置是否在窗口内,如果被判断的符号在窗口外,则说明当前窗口内无重复字符,不需要更新。
一旦被判断的字符就在窗口内,再用过去的的位置标记就不行了,否则将导致窗口内出现了重复字符,但没被检测出来的状况。所以必须更新字符出现的最新位置,这能帮助我们判断该字符是否出现在窗口内。
2、小顶堆找第K大的元素
求第k大,就要用小顶堆,每一次更新后,顶点时刻都是整个树中数值最小的节点,它的孩子都比他大,而我们求第k大,就构建一个只有 k 个节点的堆,最后返回堆顶。
[对比]->[移除]->[调整]三步