力扣3 无重复字符的最长子串
public int lengthOfLongestSubstring(String s) {
HashMap<Character,Integer> map=new HashMap<>();
int left=0;
int maxLen=0;
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(!map.containsKey(c)){
map.put(c,i);
maxLen=Math.max(maxLen,i-left+1);
}
else{
int index=map.get(c);
if(index>=left){
left=index+1;
maxLen=Math.max(maxLen,i-index);
}
else{
maxLen=Math.max(maxLen,i-left+1);
}
map.put(c,i);
}
}
return maxLen;
}
public int lengthOfLongestSubstring(String s) {
HashMap<Character,Integer> map=new HashMap<>();
int left=0;
int maxLen=0;
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(!map.containsKey(c)){
map.put(c,i);
}
else{
int index=map.get(c);
if(index>=left){
left=index+1;
}
map.put(c,i);
}
maxLen=Math.max(maxLen,i-left+1);
}
return maxLen;
}
public int lengthOfLongestSubstring(String s){
if(s.length()==0) return 0;
HashMap<Character,Integer> map=new HashMap<>();
int left=0;
int max=0;
for(int i=0;i<s.length();i++){
if(map.containsKey(s.charAt(i))){
//比如 "dvdf" ,碰到第二个 d,那么应该移动 i 到 v 这个字符,因为这样就从窗口里面把第一个 d 略过了
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;
}
力扣 76 最小覆盖子串
public String minWindow(String s, String t) {
if(s==null||s.length()==0||t==null||t.length()==0) return "";
int[] need=new int[128];
//need数组中>0表示该字符还需几个,<0表示窗口内该字符多余的数量,=0表示不需要的字符没有出现在窗口里
for(int i=0;i<t.length();i++){
need[t.charAt(i)]++;
}
int left=0;//窗口左边界
int right=0;//窗口右边界
int count=t.length();
int minSize = Integer.MAX_VALUE;
int start=0;//最小子串的最左边界
while(right<s.length()){
char c=s.charAt(right);
if(need[c]>0){
count--;
}
need[c]--;
if(count==0){
while(left<right&&need[s.charAt(left)]<0){
need[s.charAt(left)]++;
left++;
}
if(right-left+1<minSize){
minSize=right-left+1;
start=left;
}
need[s.charAt(left)]++;
left++;
count++;
}
right++;
}
return minSize==Integer.MAX_VALUE?"":s.substring(start,start+minSize);
}
剑指offer59 滑动窗口的最大值
遍历数组时的规律:
因此,队列始终是一个降序队列,队首一定是当前窗口最大值。
每一次窗口向前滑动,是右边界向右移,左边界向右移。右边界是对比数组中下一个数的大小来实现,左边界需要将当前坐标-窗口长度得到的坐标和队首元素进行对比,如果相同,说明已经不在窗口区间内,需要删掉队首元素,以达到窗口右移的效果。
public int[] maxSlidingWindow(int[] nums, int k) {
//代码分成窗口形成前和窗口形成后
if(nums.length==0||k==0) return new int[0];
Deque<Integer> deque=new LinkedList<>();
int[] res=new int[nums.length-k+1];
int index=0;
for(int i=0;i<k;i++){
while(!deque.isEmpty()&&deque.peekLast()<nums[i]) deque.removeLast();
deque.addLast(nums[i]);
}
res[index++]=deque.peekFirst();
for(int i=k;i<nums.length;i++){
if(nums[i-k]==deque.peekFirst()) deque.removeFirst();//左边界右移
while(!deque.isEmpty()&&deque.peekLast()<nums[i]) deque.removeLast();
deque.addLast(nums[i]);
res[index++]=deque.peekFirst();
}
return res;
}