算法通关村第十六关|白银|滑动窗口经典

1.最长子串

1.1 无重复字符的最长子串

原题:力扣3.

使用 HashMap ,将字符和最后一次出现的索引存储起来。

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 right = 0; right < s.length(); right++) {
        if (map.containsKey(s.charAt(right))) {
            left = Math.max(left, map.get(s.charAt(right)) + 1);
        }
        map.put(s.charAt(right), right);
        max = Math.max(max, right - left + 1);
    }
	return max;
}

1.2 至多包含两个不同字符的最长子串

原题:力扣159.

public int lengthOfLongestSubstringTwoDistinct(String s) {
	if (s.length() < 3) {
        return s.length();
	}
	int left = 0, right = 0;
	HashMap<Character, Integer> hashmap = new HashMap<>();
	int maxLen = 2;
	while (right < s.length()) {
        if (hashmap.size() < 3) {
            hashmap.put(s.charAt(right), right++);
        }
        if (hashmap.size() == 3) {
            int del_index = Collections.min(hashmap.values());
            hashmap.remove(s.charAt(del_index));
            left = del_index + 1;
        }
        maxLen = Math.max(maxLen, right - left);
    }
	return maxLen;
}

*1.3 至多包含 K 个不同字符的最长子串

原题:力扣340.

public int lengthOfLongestSubstringDistinct(String s, int k) {
	if (s.length() < k + 1) {
        return s.length();
    }
    int left = 0, right = 0;
    HashMap<Character, Integer> hashmap = new HashMap<>();
    int maxLen = k;
    while (right < s.length()) {
        if (hashmap.size() < k + 1) {
            hashmap.put(s.charAt(right), right++);
        }
        if (hashmap.size() == k + 1) {
            int del_index = Collections.min(hashmap.values());
            hashmap.remove(s.charAt(del_index);
            left = del_index + 1;
        }
        maxLen = Math.max(maxLen, right - left);
    }
    return maxLen;
}

2.长度最小的子数组

原题:力扣209.

public int minSubArrayLen(int target, int[] nums) {
	int left = 0, right = 0, sum = 0, min = Integer.MAX_VALUE;
    while (right < nums.length) {
        sum += nums[right++];
        while (sum >= target) {
            min = Math.min(min, right - left);
            sum -= nums[left++];
        }
    }
    return min == Integer.MAX_VALUE ? 0 : min;
}

3.盛水最多的容器

原题:力扣11.

双指针向中间移动直到碰撞。

public int maxArea(int[] height) {
	int i = 0, j = height.length - 1, res = 0;
    while (i < j) {
        res = height[i] < height[j] ?
        	Math.max(res, (j - i) * height[i++]) :
            Math.max(res, (j - i) * height[j--]);
    }
    return res;
}

4.寻找子串异位词(子串排列)

如果两个字符串仅仅是字母出现的位置不一样,则两者互为对方的一个排列,也叫做异位词。

4.1 字符串的排列

原题:力扣567.

这道题要求判断 s2 是否包含 s1 的排列。

public boolean checkInclusion(String s1, String s2) {
	int len1 = s1.length(), len2 = s2.length();
    if (len1 > len2) {
        return false;
    }
    // 统计每种字符出现次数
    int[] charArray1 = new int[26];
    int[] charArray2 = new int[26];
    // 先读第一段
    // 滑动窗口长度固定为 len1
    for (int i = 0; i < len1; i++) {
        // 哪个字符出现了,数组中对应的位置就加 1
        charArray1[s1.charAt(i) - 'a']++;
        charArray2[s2.charAt(i) - 'a']++;
    }
    // 比较第一段数组中字符是否数目相同
    if (Arrays.equals(charArray1, charArray2)) {
        return true;
    }
    // 开始移动窗口
    for (int right = len1; right < len2; right++) {
        // charArray1 已经存好了,不需要再变动
        charArray2[s2.charAt(right) - 'a']++;
        int left = right - len1;
        charArray2[s2.charAt(left) - 'a']--;
        if (Arrays.equals(charArray1, charArray2)) {
            return true;
        }
    }
    return false;
}

4.2 找到字符串中所有字母异位

原题:力扣438.

要求将所有符合条件的排列的起始索引返回。

public List<Integer> findAnagrams(String s, String p) {
    List<Integer> res = new ArrayList<>();
	if (s.length() < p.length()) {
        return res;
    }
    // 还是用滑动窗口做,但是这次记录起始索引

    int left = 0;
    int[] charArray1 = new int[26];
    int[] charArray2 = new int[26];
    for (int i = 0; i < p.length(); i++) {
        charArray1[s.charAt(i) - 'a']++;
        charArray2[p.charAt(i) - 'a']++;
    }
    if (Arrays.equals(charArray1, charArray2)) {
        res.add(left);
    }
    for (int right = p.length(); right < s.length(); right++) {
        charArray1[s.charAt(right) - 'a']++;
        charArray1[s.charAt(left) - 'a']--;
        left++;
        if (Arrays.equals(charArray1, charArray2)) {
            res.add(left);
        }
    }
    return res;
}

如果对您有帮助,请点赞关注支持我,谢谢!❤
如有错误或者不足之处,敬请指正!❤
个人主页:星不易
算法通关村专栏:不易|算法通关村

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值