马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
- <strong>输入:</strong>target = 7, nums = [2,3,1,2,4,3]
- <strong>输出:</strong>2
- <strong>解释:</strong>子数组 [4,3] 是该条件下的长度最小的子数组。
复制代码 示例 2:
- <strong>输入:</strong>target = 4, nums = [1,4,4]
- <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[right];
- while (sum - nums[left] >= target) { // 尽量缩小子数组长度
- sum -= nums[left++]; // 左端点右移
- }
- 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[128];
- int len = 0;
- for(int i = 0, j = 0; j < s.length(); j++){
- i = Math.max(m[s.charAt(j)], i);
- len = Math.max(len, j - i + 1);
- m[s.charAt(j)] = j + 1;
- }
- return len;
- }
- }
复制代码 1004. 最大连续1的个数 III
给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k 个 0 ,则返回执行操纵后 数组中连续 1 的最大个数 。
示例 1:
- <strong>输入:</strong>nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
- <strong>输出:</strong>6
- <strong>解释:</strong>[1,1,1,0,0,<strong>1</strong>,1,1,1,1,<strong>1</strong>]
- 粗体数字从 0 翻转到 1,最长的子数组长度为 6。
复制代码 示例 2:
- <strong>输入:</strong>nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
- <strong>输出:</strong>10
- <strong>解释:</strong>[0,0,1,1,<strong>1</strong>,<strong>1</strong>,1,1,1,<strong>1</strong>,1,1,0,0,0,1,1,1,1]
- 粗体数字从 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[right]; // 0 变成 1,用来统计 cnt0
- // 如果当前窗口中的0的个数超过k个,移动左指针直到窗口中的0的个数不超过k
- while (cnt0 > k) {
- // 减少左指针位置的0的计数
- cnt0 -= 1 - nums[left++];
- }
- // 更新最长子数组的长度
- 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 = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], minutes = 3
- <strong>输出:</strong>16
- <strong>解释:</strong>书店老板在最后 3 分钟保持冷静。
- 感到满意的最大客户数量 = 1 + 1 + 1 + 1 + 7 + 5 = 16.
复制代码 示例 2:
- <strong>输入:</strong>customers = [1], grumpy = [0], 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[2];
- // 初始化最大满意值maxS1为0
- int maxS1 = 0;
-
- // 遍历customers数组
- for (int i = 0; i < customers.length; i++) {
- // 根据grumpy数组的值,将当前顾客的满意度加到对应的s数组中
- s[grumpy[i]] += customers[i];
-
- // 如果窗口长度不足minutes,继续下一个循环
- if (i < minutes - 1) { // 窗口长度不足 minutes
- continue;
- }
-
- // 更新最大满意值maxS1
- maxS1 = Math.max(maxS1, s[1]);
-
- // 窗口最左边元素离开窗口,如果该元素是满意的,则从s[1]中减去其满意度
- s[1] -= grumpy[i - minutes + 1] > 0 ? customers[i - minutes + 1] : 0;
- }
-
- // 返回总的满意人数,即初始满意人数加上最大可能增加的满意人数
- return s[0] + maxS1;
- }
- }
复制代码 1652. 拆炸弹
你有一个炸弹必要拆除,时间紧迫!你的谍报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k 。
为了获得正确的密码,你必要更换掉每一个数字。所有数字会 同时 被更换。
- 如果 k > 0 ,将第 i 个数字用 接下来 k 个数字之和更换。
- 如果 k < 0 ,将第 i 个数字用 之前 k 个数字之和更换。
- 如果 k == 0 ,将第 i 个数字用 0 更换。
由于 code 是循环的, code[n-1] 下一个元素是 code[0] ,且 code[0] 前一个元素是 code[n-1] 。
给你 循环 数组 code 和整数密钥 k ,请你返回解密后的结果来拆除炸弹!
示例 1:
- <strong>输入:</strong>code = [5,7,1,4], k = 3
- <strong>输出:</strong>[12,10,16,13]
- <strong>解释:</strong>每个数字都被接下来 3 个数字之和替换。解密后的密码为 [7+1+4, 1+4+5, 4+5+7, 5+7+1]。注意到数组是循环连接的。
复制代码 示例 2:
- <strong>输入:</strong>code = [1,2,3,4], k = 0
- <strong>输出:</strong>[0,0,0,0]
- <strong>解释:</strong>当 k 为 0 时,所有数字都被 0 替换。
复制代码 示例 3:
- <strong>输入:</strong>code = [2,4,9,3], k = -2
- <strong>输出:</strong>[12,5,6,13]
- <strong>解释:</strong>解密后的密码为 [3+9, 2+3, 4+2, 9+4] 。注意到数组是循环连接的。如果 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[n];
- int r = k > 0 ? k + 1 : n; // 第一个窗口的右开端点
- k = Math.abs(k);
- int s = 0;
- for (int i = r - k; i < r; i++) {
- s += code[i]; // 计算 ans[0]
- }
- for (int i = 0; i < n; i++) {
- ans[i] = s;
- s += code[r % n] - code[(r - k) % n];
- r++;
- }
- return ans;
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|