《五月集训》第六日——滑动窗口

前言

这是五月集训的第六天,今日的内容是 滑动窗口

解题报告

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 码非递减排序,并且所有的字母都需要最少出现一次。那么使用一个双指针,初始位置为 01。如何保证得到了所需的字符串子串呢,需要满足以下的条件:每个字母都出先过,非递减。其中比较容易实现的是每个字母都出现,我们可以定义一个变量 t 用来储存出现过的字母数,而且只有当前一个字母的 ASCII 码要小于后一个字母时(严格要求)才使这个数加上 1 ,注意,因为第一个数是不会导致 t 的值发生变化的( a 必然是需要小于前面的字母的)因此 t 的值一共只会变化 4 次。(例如你初始化 t1 的话,满足条件的 t5)这时其实会发现,需要递增的条件也在这个时候已经实现到了,那么记录下最大的长度返回就可以了。

源码剖析

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值