滑动窗口

滑动窗口

3. 无重复字符的最长子串

class Solution {
    public int lengthOfLongestSubstring(String s) {
    	int res = 0;
    	int l = 0;
    	int r = 0;
		Map<Character, Integer> map = new HashMap<>();	//	记录字符出现个数,始终要维持 1
		char[] chars = s.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			r++;	//	无脑向前
			char temp = chars[i];
			if (map.getOrDefault(temp, 0) > 0) {
				for (int j = l; j < i; j++) {
					if (chars[j] == temp) {    //	找到了前面要加入的
						l++;
						break;
					} else {
						l++;
						map.put(chars[j], 0);	//	清空前方字符
					}
				}
			}
			map.put(temp, 1);	//	新加的数,放入 map 中
			res = Math.max(res, r - l);	//	r 是从 1 开始的(当前数的下一个位置)
		}
		return res;
	}
}

76. 最小覆盖子串

粗略实现

class Solution {
	Map<Character, Integer> targetMap = new HashMap<>();
	Map<Character, Integer> map = new HashMap<>();
	//	后面返回的是:start 和 len
    public String minWindow(String s, String t) {
		boolean flag = false;	//	能够找到
    	int start = 0;
    	int Len = s.length();	//	子串初始长度
    	int left = 0;
    	int right = 0;
    	//	只有当满足条件时吗,才考虑精简
		for (char c : t.toCharArray()) {
			 targetMap.put(c, targetMap.getOrDefault(c, 0) + 1);
		}
		char[] chars = s.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			right++;
			char temp = chars[i];	//  待考察的
			if (targetMap.containsKey(temp)) {    //	有用的就要
				map.put(temp, map.getOrDefault(temp, 0) + 1);
				if (isFull()) {	//	加完之后已经满了
					flag = true;
					for (int j = left; j <= i; j++) {	//	这里要有等号(考虑到:target 只有一个的情况【ab a】)
						if (targetMap.containsKey(chars[j])) {
							map.put(chars[j], map.get(chars[j]) - 1);	//	逐个干掉!!!
							if (!isFull()) {    //	干掉之后已经不满了
								if (Len > right - left) {
									Len = right - left;
									start = left;
								}
								left++;
								break;
							}else {
								left++;
							}
						}else {	//	无关紧要的,向右推进
							left++;
						}
					}
				}
			}
		}
		if (flag) {
			return s.substring(start, start + Len);
		}
		return "";
	}

	public boolean isFull(){
		for (Character character : targetMap.keySet()) {
			if (targetMap.get(character).compareTo(map.getOrDefault(character, -1)) > 0){
				return false;
			}
		}
		return true;
	}
}

由于都是英文字母 ===> 使用数组进行优化

class Solution {
	int[] targetMap = new int[128];
	int[] map = new int[128];
	//	后面返回的是:start 和 len
    public String minWindow(String s, String t) {
		boolean flag = false;	//	能够找到
    	int start = 0;
    	int Len = s.length();	//	子串初始长度
    	int left = 0;
    	int right = 0;
    	//	只有当满足条件时吗,才考虑精简
		for (char c : t.toCharArray()) {
			targetMap[c]++;
		}
		char[] chars = s.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			right++;
			char temp = chars[i];	//  待考察的
			if (targetMap[temp] != 0) {    //	有用的就要
				map[temp]++;
				if (isFull()) {	//	加完之后已经满了
					flag = true;
					//	这里主要还是因为我们要求的是最小值!!!(所以考虑 Len 为 1 的情况)
					for (int j = left; j <= i; j++) {	//	这里要有等号(考虑到:target 只有一个的情况【ab a】)
						if (targetMap[chars[j]] != 0) {
							map[chars[j]]--;	//	把这个干掉
							if (!isFull()) {    //	干掉之后已经不满了
								if (Len > right - left) {
									Len = right - left;
									start = left;
								}
								left++;
								break;
							}else {
								left++;
							}
						}else {	//	无关紧要的,向右推进
							left++;
						}
					}
				}
			}
		}
		if (flag) {
			return s.substring(start, start + Len);
		}
		return "";
	}

	public boolean isFull(){
		for (int i = 0; i < 128; i++) {
			if (map[i] < targetMap[i]){
				return false;
			}
		}
		return true;
	}
}

变形题【关联子串】

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
         int start = 0;
        int Len = Integer.MAX_VALUE;

        int[] targetMap = new int[128];
        int[] map = new int[128];
        Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        String target = split[0];
        String str = split[1];
        for (char c : target.toCharArray()) {
            targetMap[c]++;
        }
        int res = -1;
        int left = 0;
        int right = 0;
        for (int i = 0; i < str.length(); i++) {
            right++;
            char temp = str.charAt(i);
            if (targetMap[temp] != 0) {  //  有用的
                map[temp]++;
                if (isFull(map, targetMap)) {  //  现在满了,开始向前清算 ---> 干掉多余的
                    for (int j = left; j <= i; j++) {
                        char c = str.charAt(j);
                        if (targetMap[c] != 0) { //  有用的
                            map[c]--;   //  将这个有用的干掉
                            if (!isFull(map, targetMap)) {
                                if (Len > right - left) {  // right - left 最小值就是 target.length()
                                    Len = right - left;
                                    start = left;  //  所以就只更新一次
                                }
                                left++;
                                break;
                            }else {
                                left++;
                            }
                        } else {
                            left++;
                        }
                    }
                }
            }
        }
        if (Len != target.length()){
            System.out.println(-1);
            return;
        }
        System.out.println(start);
    }
     public static boolean isFull(int[] map, int[] targetMap){
        for (int i = 0; i < 128; i++) {
            if (map[i] < targetMap[i]){
                return false;
            }
        }
        return true;
    }
}

438. 找到字符串中所有字母异位词

class Solution {
	int[] now = new int[128];
	int[] target = new int[128];

	public List<Integer> findAnagrams(String s, String p) {
		for (char c : p.toCharArray()) {
			target[c-'a']++;
		}
		List<Integer> list = new ArrayList<>();
		int l = 0;
    	int r = 0;
		for (int i = 0; i < s.length(); i++) {
			r++;
			now[s.charAt(i) - 'a']++;	//	维护一个滑动窗口!!!
			if (r - l < p.length()){
				continue;
			}
			//	长度够了现在
			if (isSame()) {
				list.add(l);
			}
			now[s.charAt(l) - 'a']--;	//	减去头
			l++;
		}
		return list;
    }
    public boolean isSame(){
		for (int i = 0; i < 128; i++) {
			if (now[i] != target[i]){
				return false;
			}
		}
		return true;
	}
}
posted @ 2023-09-04 00:26  爱新觉罗LQ  阅读(5)  评论(0编辑  收藏  举报