前言
这是五月集训的第六天,今日的内容是 滑动窗口
解题报告
1.力扣1984
原题链接
https://leetcode-cn.com/problems/minimum-difference-between-highest-and-lowest-of-k-scores/
题目概述
给你一个 下标从 0 开始 的整数数组 nums ,其中 nums[i] 表示第 i 名学生的分数。另给你一个整数 k 。
从数组中选出任意 k 名学生的分数,使这 k 个分数间 最高分 和 最低分 的 差值 达到 最小化 。
返回可能的 最小差值 。
解题思路
首先就原来的数组排序,然后使用一个滑动窗口,并记录下两端的差值,最后返回最小差值就可以了。
源码剖析
int cmp(const void*a,const void*b){
return *(int*)a-*(int*)b;
}
int minimumDifference(int* nums, int numsSize, int k){
qsort(nums,numsSize,sizeof(int),cmp);
int i,j;
int min=100000;
for(j=k-1,i=0;j<numsSize;++i,++j){
if(nums[j]-nums[i]<=min) min=nums[j]-nums[i];
}
return min;
}
只需要简单的写一个循环遍历数组就好了。
2.力扣1876
原题链接
https://leetcode-cn.com/problems/substrings-of-size-three-with-distinct-characters/
题目概述
如果一个字符串不含有任何重复字符,我们称这个字符串为 好 字符串。
给你一个字符串 s ,请你返回 s 中长度为 3 的 好子字符串 的数量。
注意,如果相同的好子字符串出现多次,每一次都应该被记入答案之中。
子字符串 是一个字符串中连续的字符序列。
解题思路
这题的子串的长度非常的短,甚至其实可以不使用哈希表直接判断就可以了。简单的遍历一下字符串就可以了。
源码剖析
int countGoodSubstrings(char * s){
int i,j,ans=0;
int len = strlen(s);
for(i=0,j=2;j<len;++i,++j){
if(s[i]==s[j]) continue;
if(s[i]==s[i+1]) continue;
if(s[i+1]==s[j]) continue;
ans++;
}
return ans;
}
在循环中写入三个判断,如果都不满足说明三个元素都不相等,那么计数器加一,最后返回计数器即可。
3.力扣1839
原题链接
https://leetcode-cn.com/problems/longest-substring-of-all-vowels-in-order/
题目概述
当一个字符串满足如下条件时,我们称它是 美丽的 :
所有 5 个英文元音字母(‘a’ ,‘e’ ,‘i’ ,‘o’ ,‘u’)都必须 至少 出现一次。
这些元音字母的顺序都必须按照 字典序 升序排布(也就是说所有的 ‘a’ 都在 ‘e’ 前面,所有的 ‘e’ 都在 ‘i’ 前面,以此类推)
比方说,字符串 “aeiou” 和 “aaaaaaeiiiioou” 都是 美丽的 ,但是 “uaeio” ,“aeoiu” 和 “aaaeeeooo” 不是美丽的 。给你一个只包含英文元音字母的字符串 word ,请你返回 word 中 最长美丽子字符串的长度 。如果不存在这样的子字符串,请返回 0 。
子字符串 是字符串中一个连续的字符序列。
解题思路
首先,题目中有说到,所给的所有的字符串全部都满足在 aiueo 这些字母中,这为接下来的判断等提供的许多的便利。因为这五个字母的 ASCII 码的大小与题目中所给的“美丽字符串”的顺序是刚刚好的,那么也就是说所谓的美丽字符串需要满足 ASCII 码非递减排序,并且所有的字母都需要最少出现一次。那么使用一个双指针,初始位置为 0 和 1。如何保证得到了所需的字符串子串呢,需要满足以下的条件:每个字母都出先过,非递减。其中比较容易实现的是每个字母都出现,我们可以定义一个变量 t 用来储存出现过的字母数,而且只有当前一个字母的 ASCII 码要小于后一个字母时(严格要求)才使这个数加上 1 ,注意,因为第一个数是不会导致 t 的值发生变化的( a 必然是需要小于前面的字母的)因此 t 的值一共只会变化 4 次。(例如你初始化 t 为 1 的话,满足条件的 t 是 5)这时其实会发现,需要递增的条件也在这个时候已经实现到了,那么记录下最大的长度返回就可以了。
源码剖析
int longestBeautifulSubstring(char * word){
int len = strlen (word);
if(len<5) return 0;
int i,j,t = 1;
int max = 0;
for(i=0,j=1;j<len;j++){
if(word[j]<word[j-1]){ //(1)
i = j;
t = 1;
}
if(word[j]>word[j-1]) t++;
if(t==5){
if(j-i+1>max) max=j-i+1; //(2)
}
}
return max;
}
1.若是没有出现满足条件的情况,直接将前一个指针定向到后一个指针的位置,因为半路都不可能出现满足条件的情况,不需要去判断。
2.字符串的长度是下标之差再加上1。
4.力扣1052
原题链接
https://leetcode-cn.com/problems/grumpy-bookstore-owner/
题目概述
有一个书店老板,他的书店开了 n 分钟。每分钟都有一些顾客进入这家商店。给定一个长度为 n 的整数数组 customers ,其中 customers[i] 是在第 i 分钟开始时进入商店的顾客数量,所有这些顾客在第 i 分钟结束后离开。
在某些时候,书店老板会生气。 如果书店老板在第 i 分钟生气,那么 grumpy[i] = 1,否则 grumpy[i] = 0。
当书店老板生气时,那一分钟的顾客就会不满意,若老板不生气则顾客是满意的。
书店老板知道一个秘密技巧,能抑制自己的情绪,可以让自己连续 minutes 分钟不生气,但却只能使用一次。
请你返回 这一天营业下来,最多有多少客户能够感到满意 。
解题思路
对 grumpy[]
数组进行处理,并且对原来的数字遍历,求出最大满意值就可以了。
源码剖析
int maxSatisfied(int* customers, int customersSize, int* grumpy, int grumpySize, int X){
int i;
int sum = 0;
int res = 0;
/* 窗口[0,X-1]内顾客都满意 */
for (i = 0; i < X; i++) {
sum += customers[i];
}
/* 统计[0,X-1]窗口外的顾客满意人数 */
for (; i < customersSize; i++) {
sum += (grumpy[i] == 0) ? customers[i] : 0;
}
res = sum;
/* 滑动窗口, 每次进一人出一人, 计算满意人数 */
for (i = 1; i <= customersSize - X; i++) {
sum -= customers[i - 1] * grumpy[i - 1]; /* 原窗口内生气的要减去 */
sum += customers[i - 1 + X] * grumpy[i - 1 + X]; /* 新进窗口的, 生气的要加上 */
res = fmax(res, sum);
}
return res;
}