leetcode--滑动窗口系列

题目
424. 替换后的最长重复字符
给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。

注意:字符串长度 和 k 不会超过 104。

示例 1:

输入:s = “ABAB”, k = 2
输出:4
解释:用两个’A’替换为两个’B’,反之亦然。
示例 2:

输入:s = “AABABBA”, k = 1
输出:4
解释:
将中间的一个’A’替换为’B’,字符串变为 “AABBBBA”。
子串 “BBBB” 有最长重复字母, 答案为 4。
思路
重要剖析:
k 个任意字符可以视为集五福中的万能福,left 就是窗口的左边。right 窗口的右边
整体思路就是用k个万能福构造一个大窗口,连续字符,只要不停向前扩展。如果实在不行了。就把左边的尾巴砍掉一截,如果没有找到更长的,我就类似平移。虽然出现次数最多的字母可能会变化,但是长度一直是在变大即可。
详细解析:
碰到统计大写字母次数的。直接把26个大小的数组建起来。(空间换时间,老套路了)
这个题目需要维护一个max变量,存一下当前窗口出现次数最多的字母的次数
看看哪个字母出现的最多,只有最多的 加上k 有可能会是最大的
从头开始遍历,遍历到一个那个字母个数+1
完后和max 取一下更大的。就是当前字符串中出现次数最多的那个字母的次数
如果+k 还是 不如当前字符串长度大,完了。这个k个万能福 也填不满你的空虚,你就缩一下吧。left++
并且减一下当前left那个字母的个数
继续向前扩展right++,如果k个万能福是填满的话,不用缩left, right继续向前!
最后返回 这个窗口的大小。
代码

    private int[] map = new int[26];
    public int characterReplacement(String s, int k) {
            	int left = 0;
    	int max = 0;
    	for (int right = 0;right  < s.length();right++) {
            int index = s.charAt(right) - 'A';
            map[index]++;
    		max = Math.max(max, map[index]);
			if (max + k < right - left + 1) {
				map[s.charAt(left) - 'A']--;
				left++;
			}
    	}
    	return s.length() - left;
    }


题目:
1004. 最大连续1的个数 III
给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。

返回仅包含 1 的最长(连续)子数组的长度。

示例 1:

输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:
[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:

输入:A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:
[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。

提示:

1 <= A.length <= 20000
0 <= K <= A.length
A[i] 为 0 或 1

思路:
从头开始遍历,记录左端点left,右端点向前,如果遍历到0,0的个数加1,如果当前窗口内0的个数已经大于K,开始缩left,当 窗口内0的个数小于等于K,右端点再继续向前,记录窗口的大小的最大值
代码:

 public int longestOnes(int[] A, int K) {
 	int res = 0;
 	int zeros = 0;
 	int left = 0;
 	int n = A.length;
 	for (int i = 0;i < n;i++) {
 		if (A[i] == 0) {
 			zeros++;
 			while (zeros > K) {
 				if (A[left++] == 0) {
 					zeros--;
 				}
 			}
 		}
 		res = Math.max(res, i - left + 1);
 	} 
 	return res;
 }

题目:
697. 数组的度
给定一个非空且只包含非负数的整数数组 nums,数组的度的定义是指数组里任一元素出现频数的最大值。

你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。

示例 1:

输入:[1, 2, 2, 3, 1]
输出:2
解释:
输入数组的度是2,因为元素1和2的出现频数最大,均为2.
连续子数组里面拥有相同度的有如下所示:
[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
最短连续子数组[2, 2]的长度为2,所以返回2.
示例 2:

输入:[1,2,2,3,1,4,2]
输出:6

提示:

nums.length 在1到 50,000 区间范围内。
nums[i] 是一个在 0 到 49,999 范围内的整数。
通过次数32,641提交次数57,959
思路:
数组效率高于map,首先求出来最大度数,采取数组

然后采用双指针滑动窗口的的方式,从左边开始向右滑,
使用map存储 出现元素的次数,和元素本身
如果当前遍历到的元素已经出现最大度数,求出当前窗口大小,并且左指针 向右滑,求出最短窗口的长度
代码:

    public int findShortestSubArray(int[] nums) {
        int[] arr = new int[50001];
        int max = 0;
        for (int i : nums) {
            arr[i]++;
            max = arr[i] > arr[max] ? i : max;
        }

        int l = 0,r = 0, len = nums.length, res = len + 1;
        Map<Integer, Integer> map = new HashMap<>();
        for (int right = 0; right < len;right++) {
            map.put(nums[right], map.getOrDefault(nums[right], 0) + 1);
            while (map.get(nums[right]) == arr[max]) {
                res = Math.min(res, right - l + 1);
                map.put(nums[l], map.get(nums[l]) - 1);
                l++;
            }
        }
        
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值