暑假算法日记第一天

目标​:刷完灵神专题训练算法题单

阶段目标📌:【算法题单】滑动窗口与双指针

LeetCode题目:

  • [1456. 定长子串中元音的最大数目](#1456. 定长子串中元音的最大数目)
  • [643. 子数组最大平均数 I](#643. 子数组最大平均数 I)
  • [1343. 大小为 K 且平均值大于等于阈值的子数组数目](#1343. 大小为 K 且平均值大于等于阈值的子数组数目)
  • [2090. 半径为 k 的子数组平均值](#2090. 半径为 k 的子数组平均值)
  • [2379. 得到 K 个黑块的最少涂色次数](#2379. 得到 K 个黑块的最少涂色次数)
  • [2841. 几乎唯一子数组的最大和](#2841. 几乎唯一子数组的最大和)

其他:

今日总结


1456. 定长子串中元音的最大数目

跳转:
学习: 灵神:教你解决定长滑窗!

问题:

给你字符串 s 和整数 k

请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。

英文中的 元音字母 为(a, e, i, o, u)。

思路:

定长滑动窗口,先装入元素,根据题目要求更新,窗口满员则下次装入前先退出末尾元素。

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

代码:

python3 复制代码
class Solution:
    def maxVowels(self, s: str, k: int) -> int:
        ans = vowel = 0
        for i,c in enumerate(s):
            if c in "aeiou":
                vowel += 1
            if i < k - 1:
                continue
            ans = max(ans,vowel)
            if s[i - k + 1] in "aeiou":
                vowel -= 1
        return ans

643. 子数组最大平均数 I

跳转:

问题:

给你一个由 n 个元素组成的整数数组 nums 和一个整数 k

请你找出平均数最大且 长度为 k 的连续子数组,并输出该最大平均数。

任何误差小于 10-5 的答案都将被视为正确答案。

思路:

滑动窗口求最大值,题目条件保证 k < = n k <= n k<=n 。可以先初始化为前k个元素作为初始窗口,然后边移动边比较

本质上还是入-更新-出,相当于初始化并更新,然后倒出-装入-更新。倒出-装入一步完成

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

代码:

python3 复制代码
class Solution:
    def findMaxAverage(self, nums: List[int], k: int) -> float:
        maxArgv = temp = sum(nums[:k])
        for idx in range(0,len(nums)-k):
            temp += nums[idx+k] - nums[idx]
            maxArgv = max(maxArgv,temp)
        return maxArgv / k

1343. 大小为 K 且平均值大于等于阈值的子数组数目

跳转:

问题:

给你一个整数数组 arr 和两个整数 kthreshold

请你返回长度为 k 且平均值大于等于 threshold 的子数组数目。

思路:

这里要求计数,首先threshold与k是整数,商和除数为整数的情况下求被除数不用考虑精度,所以可以直接用threshold * k卡计数条件,初始化-更新,出入-更新滑动窗口即可。

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

代码:

python3 复制代码
class Solution:
    def numOfSubarrays(self, arr: List[int], k: int, threshold: int) -> int:
        ans = 0
        Bound = threshold * k
        temp = sum(arr[:k])
        if temp >= Bound:
            ans += 1
        for idx in range(0,len(arr)-k):
            temp += arr[idx + k] - arr[idx]
            if temp >= Bound:
                ans += 1
        return ans

2090. 半径为 k 的子数组平均值

跳转:

问题:

给你一个下标从 0 开始的数组 nums ,数组中有 n 个整数,另给你一个整数 k

半径为 k 的子数组平均值 是指:nums 中一个以下标 i中心半径k 的子数组中所有元素的平均值,即下标在 i - ki + k 范围( i - ki + k)内所有元素的平均值。如果在下标 i 前或后不足 k 个元素,那么 半径为 k 的子数组平均值-1

构建并返回一个长度为 n 的数组 avgs ,其中 avgs[i] 是以下标 i 为中心的子数组的 半径为 k 的子数组平均值

x 个元素的 平均值x 个元素相加之和除以 x ,此时使用截断式 整数除法 ,即需要去掉结果的小数部分。

  • 例如,四个元素 2315 的平均值是 (2 + 3 + 1 + 5) / 4 = 11 / 4 = 2.75,截断后得到 2

思路:

可以看作是窗口大小为 2 * k + 1 的滑动窗口,但更新是在中点处更新,这里采用覆盖的方式更新值

本质上还是入-更新-出,相当于初始化并更新,然后倒出-装入-更新。倒出-装入一步完成

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

代码:

python3 复制代码
class Solution:
    def getAverages(self, nums: List[int], k: int) -> List[int]:
        size = k * 2 + 1
        avgs = [-1 for _ in range(len(nums))]
        if len(nums) < size:
            return avgs
        temp = sum(nums[:size])
        avgs[k] = temp // size
        for idx in range(0,len(nums) - size):
            temp += nums[idx + size] - nums[idx]
            avgs[idx + k + 1] = temp // size
        return avgs

2379. 得到 K 个黑块的最少涂色次数

跳转:

问题:

给你一个长度为 n 下标从 0 开始的字符串 blocksblocks[i] 要么是 'W' 要么是 'B' ,表示第 i 块的颜色。字符 'W''B' 分别表示白色和黑色。

给你一个整数 k ,表示想要 连续 黑色块的数目。

每一次操作中,你可以选择一个白色块将它 涂成 黑色块。

请你返回至少出现 一次 连续 k 个黑色块的 最少 操作次数。

思路:

相当于在大小为k的窗口中求白色快最少数量

每一个都需要判断,不是简单加和,所以不能偷懒,入-更新-出

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

代码:

python3 复制代码
class Solution:
    def minimumRecolors(self, blocks: str, k: int) -> int:
        ans = k
        temp = 0
        for idx,value in enumerate(blocks):
            if value == 'W':
                temp += 1
            if idx < k - 1:
                continue
            ans = min(temp,ans)
            if blocks[idx - k + 1] == 'W':
                temp -= 1
        return ans

2841. 几乎唯一子数组的最大和

跳转:

问题:

给你一个整数数组 nums 和两个正整数 mk

请你返回 nums 中长度为 k几乎唯一 子数组的 最大和 ,如果不存在几乎唯一子数组,请你返回 0

如果 nums 的一个子数组有至少 m 个互不相同的元素,我们称它是 几乎唯一 子数组。

子数组指的是一个数组中一段连续 非空 的元素序列。

思路:

入-更新-出,但只在满足不重复元素大于等于m的情况下更新

这里维护字典键值对数来判断不重复元素有多少

复杂度:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

代码:

python3 复制代码
class Solution:
    def maxSum(self, nums: List[int], m: int, k: int) -> int:
        ans = cnt = 0
        dict_num = {}
        for idx,num in enumerate(nums):
            cnt += num
            if num in dict_num:
                dict_num[num] += 1
            else:
                dict_num[num] = 1
            if idx < k - 1:
                continue
            if len(dict_num) >= m:
                ans = max(ans,cnt)
            temp = nums[idx - k + 1]
            cnt -= temp
            if dict_num[temp] == 1:
                del dict_num[temp]
            else:
                dict_num[temp] -= 1
        return ans

总结

练习了定长滑动窗口基础题目,思路模板为入-更新-出,不一定是简单的增删改元素,要考虑有条件的增删改

*[1456. 定长子串中元音的最大数目]: LeetCode
*[643. 子数组最大平均数 I]: LeetCode
*[2841. 几乎唯一子数组的最大和]: LeetCode
*[2090. 半径为 k 的子数组平均值]: LeetCode
*[2379. 得到 K 个黑块的最少涂色次数]: LeetCode
*[1343. 大小为 K 且平均值大于等于阈值的子数组数目]: LeetCode

相关推荐
张人玉1 小时前
C# 常量与变量
java·算法·c#
weixin_446122462 小时前
LinkedList剖析
算法
百年孤独_3 小时前
LeetCode 算法题解:链表与二叉树相关问题 打打卡
算法·leetcode·链表
我爱C编程3 小时前
基于拓扑结构检测的LDPC稀疏校验矩阵高阶环检测算法matlab仿真
算法·matlab·矩阵·ldpc·环检测
算法_小学生3 小时前
LeetCode 75. 颜色分类(荷兰国旗问题)
算法·leetcode·职场和发展
运器1233 小时前
【一起来学AI大模型】算法核心:数组/哈希表/树/排序/动态规划(LeetCode精练)
开发语言·人工智能·python·算法·ai·散列表·ai编程
算法_小学生3 小时前
LeetCode 287. 寻找重复数(不修改数组 + O(1) 空间)
数据结构·算法·leetcode
岁忧3 小时前
(LeetCode 每日一题) 1865. 找出和为指定值的下标对 (哈希表)
java·c++·算法·leetcode·go·散列表
alphaTao3 小时前
LeetCode 每日一题 2025/6/30-2025/7/6
算法·leetcode·职场和发展
ゞ 正在缓冲99%…3 小时前
leetcode67.二进制求和
算法·leetcode·位运算