【LeetCode滑动窗口】最大连续1的个数&替换后的最长重复字符&尽可能使字符串相等&k个不同整数的子数组

最大连续1的个数

给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。

返回仅包含 1 的最长(连续)子数组的长度。
在这里插入图片描述

思路

我们使用双指针,也就是滑动窗口的方法来解这两个题
我们的思路是 让后指针一直往后移动 同时每移动一次 统计一次当前不符合条件的元素的个数
当不符合条件的元素个数超过给定k的时候,我们让前指针向后移动
直至不符合条件的个数小于等于k 继续让right向后移动
依次进行 直至right到达数组的末尾

在这里插入图片描述
上边我画了一个简单的示意图 也是希望大家可以看懂

然后就是代码了

int longestOnes(vector<int>& A, int K) {
	int left = 0;
	int right = 0;
	int ans = 0;

	int count = 0;//统计窗口中的0的个数
	while (right < A.size()) {

		if (A[right] == 0) {
			count++;
		}
		while (count > K) {

			if (A[left] == 0) {
				count--;
			}
			left++;
		}

		ans = max(ans, right - left + 1);
		right++;
	}
	return ans;
}

替换后的最长重复字符

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

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

在这里插入图片描述
这个思路和上边的题的思路完全相同 唯一不同的地方就是 字符比上个题多一些

在这里插入图片描述
这个我没有写太多 直接看代码

int characterReplacement(string s, int k) {
	int left = 0;
	int right = 0;
	int cur = 0;//当前有几个字符不符合 

	int ans = 0;
	int count[26]{ 0 };//统计每个字符的个数

	while (right < s.size()) {

		count[s[right] - 'A']++;

		cur = max(cur, count[s[right] - 'A']);//符合的最多个数
		while (right - left + 1 - cur > k) {
			//不符合的大于k
			count[s[left] - 'A']--;
			left++;
		}

		ans = max(ans, right - left + 1);
		right++;

	}
	return ans;
}

尽可能使字符串相等

给你两个长度相同的字符串,s 和 t。

将 s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]| 的开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。

用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。

如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。

如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0。

在这里插入图片描述

看这个题的题目 我们可能会想到前缀和 或者是滑动窗口
我们首先将两个字符串的相差的绝对值 计算出来
然后判断连续 最长数组之和 小于所给最大数 的最大长度

也可以使用前缀和的思想 将各位数字累加起来
求得两数之差小于最大开销 的最大长度

 //2021.2.5
    int equalSubstring(string s, string t, int maxCost) {
   vector<int> arr;
	int cur = 0;
	arr.push_back(0);
	for (int i = 0; i < s.size(); i++) {
		cur+=abs(t[i] - s[i]);
		arr.push_back(cur);//前缀和的思想
	}
    int left = 0;
	int right = 0;
	int temp = 0;
	int ans = 0;
	while (right < arr.size()) {
		temp = arr[right] - arr[left];
		while (temp > maxCost) {
			left++;
			temp= arr[right] - arr[left];
		}
		ans = max(ans, right - left);
		right++;
	}
    return ans;
    }

这个题我就不给出图了 因为上边两个题的图已经很清晰了

992. k个不同整数的子数组(困难)

给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续、不一定独立的子数组为好子数组。

(例如,[1,2,3,1,2] 中有 3 个不同的整数:1,2,以及 3。)

返回 A 中好子数组的数目。
在这里插入图片描述
按照上边那种方式会有一些答案的遗漏

因为我们只有当当前窗口中的不同整数的数量不同的时候才会向前移动left指针
但是题目要求我们统计所有的数量
在这里插入图片描述
所以我们就需要弄一个临时指针 一旦窗口中的元素的个数 符合题意 我们就从left指向right
把所有的答案加上 这样就不会有遗漏
我这里是用哈希表统计的 所以就存在一个还原哈希表的问题

代码

 int subarraysWithKDistinct(vector<int>& A, int K) {
        	int left = 0;
	int right = 0;
	int ans = 0;
	map<int, int> hash;
	while (right < A.size()) {
		hash[A[right]]++;

		while (hash.size() > K) {
			hash[A[left]]--;
			if (hash[A[left]] <= 0) {
				hash.erase(A[left]);
			}
			left++;
		}

		int t = left;//临时指针
		while (hash.size() == K) {
			ans++;
			hash[A[t]]--;
			if (hash[A[t]] <= 0) {
				hash.erase(A[t]);
			}
			t++;
		}

		while (t > left) {//还原哈希表
			hash[A[t - 1]]++;
			t--;
		}
		right++;

	}
	return ans;

    }

在这里插入图片描述

希望我上边所写对大家有帮助

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值