滑动窗口 leetcode.209.3.1004.1208
209. 长度最小的子数组给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target 的长度最小的 子数组 ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
<strong>输入:</strong>target = 7, nums =
<strong>输出:</strong>2
<strong>解释:</strong>子数组 是该条件下的长度最小的子数组。
示例 2:
<strong>输入:</strong>target = 4, nums =
<strong>输出:</strong>1 解法:滑动窗口
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int n = nums.length;
int ans = n + 1;
int sum = 0; // 子数组元素和
int left = 0; // 子数组左端点
for (int right = 0; right < n; right++) { // 枚举子数组右端点
sum += nums;
while (sum - nums >= target) { // 尽量缩小子数组长度
sum -= nums; // 左端点右移
}
if (sum >= target) {
ans = Math.min(ans, right - left + 1);
}
}
return ans <= n ? ans : 0;
}
}
3. 无重复字符的最长子串
给定一个字符串 s ,请你找出此中不含有重复字符的 最长 子串 的长度。
示例 1:
<strong>输入: </strong>s = "abcabcbb"
<strong>输出: </strong>3
<strong>解释:</strong> 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
<strong>输入: </strong>s = "bbbbb"
<strong>输出: </strong>1
<strong>解释: </strong>因为无重复字符的最长子串是 "b",所以其长度为 1。 解法一:滑动窗口
class Solution {
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 i = 0; i < s.length(); i ++){
if(map.containsKey(s.charAt(i))){
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;
}
} 解法二:精简版滑动窗口
class Solution {
public int lengthOfLongestSubstring(String s) {
int[] m = new int;
int len = 0;
for(int i = 0, j = 0; j < s.length(); j++){
i = Math.max(m, i);
len = Math.max(len, j - i + 1);
m = j + 1;
}
return len;
}
} 1004. 最大连续1的个数 III
给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k 个 0 ,则返回执行操纵后 数组中连续 1 的最大个数 。
示例 1:
<strong>输入:</strong>nums = , K = 2
<strong>输出:</strong>6
<strong>解释:</strong>
粗体数字从 0 翻转到 1,最长的子数组长度为 6。 示例 2:
<strong>输入:</strong>nums = , K = 3
<strong>输出:</strong>10
<strong>解释:</strong>
粗体数字从 0 翻转到 1,最长的子数组长度为 10。 解法:滑动窗口
统计窗口内 0 的个数 cnt0,则问题转换成在 cnt0≤k 的条件下,窗口大小的最大值。
class Solution {
public int longestOnes(int[] nums, int k) {
// 初始化最长子数组长度为0
int ans = 0;
// 初始化当前窗口中0的个数为0
int cnt0 = 0;
// 初始化左指针位置为0
int left = 0;
// 遍历数组,右指针从0到数组末尾
for (int right = 0; right < nums.length; right++) {
// 如果当前元素是0,则增加cnt0计数
cnt0 += 1 - nums; // 0 变成 1,用来统计 cnt0
// 如果当前窗口中的0的个数超过k个,移动左指针直到窗口中的0的个数不超过k
while (cnt0 > k) {
// 减少左指针位置的0的计数
cnt0 -= 1 - nums;
}
// 更新最长子数组的长度
ans = Math.max(ans, right - left + 1);
}
// 返回最长子数组的长度
return ans;
}
}
1052. 爱生气的书店老板
有一个书店老板,他的书店开了 n 分钟。每分钟都有一些顾客进入这家商店。给定一个长度为 n 的整数数组 customers ,此中 customers 是在第 i 分钟开始时进入商店的顾客数量,所有这些顾客在第 i 分钟竣事后脱离。
在某些分钟内,书店老板会生气。 如果书店老板在第 i 分钟生气,那么 grumpy = 1,否则 grumpy = 0。
当书店老板生气时,那一分钟的顾客就会不满足,若老板不生气则顾客是满足的。
书店老板知道一个机密技巧,能抑制自己的感情,可以让自己连续 minutes 分钟不生气,但却只能使用一次。
请你返回 这一天营业下来,最多有多少客户可以或许感到满足 。
示例 1:
<strong>输入:</strong>customers = , grumpy = , minutes = 3
<strong>输出:</strong>16
<strong>解释:</strong>书店老板在最后 3 分钟保持冷静。
感到满意的最大客户数量 = 1 + 1 + 1 + 1 + 7 + 5 = 16.
示例 2:
<strong>输入:</strong>customers = , grumpy = , minutes = 1
<strong>输出:</strong>1 解法:定长滑动窗口
本题可以拆分成两个问题:
老板不生气时的顾客数量之和 s0这些顾客可以感到满足。
长度为 minutes 的连续子数组中,老板生气时的顾客数量之和 s1的最大值 maxS1 。这些顾客可以感到满足。
终极答案为 s0+maxS1。
class Solution {
public int maxSatisfied(int[] customers, int[] grumpy, int minutes) {
// 初始化一个长度为2的数组s,用于存储满意和不满意的总人数
int[] s = new int;
// 初始化最大满意值maxS1为0
int maxS1 = 0;
// 遍历customers数组
for (int i = 0; i < customers.length; i++) {
// 根据grumpy数组的值,将当前顾客的满意度加到对应的s数组中
s] += customers;
// 如果窗口长度不足minutes,继续下一个循环
if (i < minutes - 1) { // 窗口长度不足 minutes
continue;
}
// 更新最大满意值maxS1
maxS1 = Math.max(maxS1, s);
// 窗口最左边元素离开窗口,如果该元素是满意的,则从s中减去其满意度
s -= grumpy > 0 ? customers : 0;
}
// 返回总的满意人数,即初始满意人数加上最大可能增加的满意人数
return s + maxS1;
}
}
1652. 拆炸弹
你有一个炸弹必要拆除,时间紧迫!你的谍报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k 。
为了获得正确的密码,你必要更换掉每一个数字。所有数字会 同时 被更换。
[*]如果 k > 0 ,将第 i 个数字用 接下来 k 个数字之和更换。
[*]如果 k < 0 ,将第 i 个数字用 之前 k 个数字之和更换。
[*]如果 k == 0 ,将第 i 个数字用 0 更换。
由于 code 是循环的, code 下一个元素是 code ,且 code 前一个元素是 code 。
给你 循环 数组 code 和整数密钥 k ,请你返回解密后的结果来拆除炸弹!
示例 1:
<strong>输入:</strong>code = , k = 3
<strong>输出:</strong>
<strong>解释:</strong>每个数字都被接下来 3 个数字之和替换。解密后的密码为 。注意到数组是循环连接的。
示例 2:
<strong>输入:</strong>code = , k = 0
<strong>输出:</strong>
<strong>解释:</strong>当 k 为 0 时,所有数字都被 0 替换。
示例 3:
<strong>输入:</strong>code = , k = -2
<strong>输出:</strong>
<strong>解释:</strong>解密后的密码为 。注意到数组是循环连接的。如果 k 是负数,那么和为 <strong>之前</strong> 的数字。 解法:滑动窗口
注意无论 k>0 还是 k<0,窗口都在向右移动,只有初始位置差别。以是确定好第一个窗口的位置,就可以把 k>0 和 k<0 两种情况合并起来了:
k>0,第一个窗口的的下标范围为 [1,k+1)。
k<0,第一个窗口的的下标范围为 [n−∣k∣,n)。
无论 k 是正是负,窗口的大小都是 ∣k∣。
在窗口向右滑动时,设移入窗口的元素下标为 rmodn,则移出窗口的元素下标为 (r−∣k∣)modn。
代码实现时,k=0 的特判可以省略。
class Solution {
public int[] decrypt(int[] code, int k) {
int n = code.length;
int[] ans = new int;
int r = k > 0 ? k + 1 : n; // 第一个窗口的右开端点
k = Math.abs(k);
int s = 0;
for (int i = r - k; i < r; i++) {
s += code; // 计算 ans
}
for (int i = 0; i < n; i++) {
ans = s;
s += code - code[(r - k) % n];
r++;
}
return ans;
}
}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]