Leetcode 643. Maximum Average Subarray I

本文详细解析了LeetCode上一道关于寻找最大平均数子数组的问题,通过C++实现了一个解决方案,展示了如何使用滑动窗口技巧来高效计算任意长度为k的子数组的最大平均值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章作者:Tyan
博客:noahsnail.com  |  优快云  |  简书

1. Description

Maximum Average Subarray I

2. Solution

class Solution {
public:
    double findMaxAverage(vector<int>& nums, int k) {
        double sum = 0;
        double mean = 0;
        double max = 0;
        for(int i = 0; i < k; i++) {
            sum += nums[i];
            mean = sum / k;
            max = sum;
        }
        for(int i = k; i < nums.size(); i++) {
            sum = sum - nums[i - k] + nums[i];
            if(sum > max) {
                max = sum;
                mean = sum / k;
            }
        }
        return mean;
    }
};

Reference

  1. https://leetcode.com/problems/maximum-average-subarray-i/description/
<think>好的,用户之前问过关于吃凉东西导致暴躁的原因,现在转到了Golang的滑动窗口算法题代码模板和变式。我需要先确定用户的需求。可能用户正在准备面试,需要算法方面的帮助。滑动窗口是常见的算法题类型,用户想要一个通用的代码模板,以及了解不同的变式,这样在遇到不同题目时可以灵活应用。 首先,我需要回忆滑动窗口算法的基本结构。滑动窗口通常用于解决数组/字符串的子数组、子串问题,比如最大/最小的满足条件的子数组。模板一般包括初始化左右指针、右指针右移、满足条件时收缩左指针、更新结果等步骤。 然后,用户还问到有多少种题目变式。常见的变式可能包括固定窗口大小、可变窗口大小、需要维护数据结构(如哈希表、前缀和)的情况,以及不同的条件判断,比如最长无重复子串、最小覆盖子串、找到所有字母异位词等。需要列举几种典型的变式,并给出对应的例子,帮助用户理解。 接下来,需要用Golang写出模板。要注意Golang的特性,比如使用for循环、map来维护字符计数等。代码模板需要简洁明了,关键部分加上注释,方便用户理解每个步骤的作用。同时,每个变式题目需要给出对应的LeetCode例题和代码示例,这样用户可以参考具体实现。 可能用户需要的是模板的通用性,所以在模板中需要指出哪些部分是需要根据题目调整的,比如如何判断窗口是否满足条件、如何更新结果等。同时,要提醒用户注意边界条件,比如右指针的移动时机、窗口收缩的条件等。 另外,用户可能对滑动窗口的不同变式数量感兴趣,需要总结常见的几种类型,并说明它们的区别,比如固定窗口和可变窗口的不同应用场景。这样用户在遇到新题时,可以判断属于哪种类型,从而套用相应的解题思路。 最后,确保回答结构清晰,分点列出模板和变式,每个部分都有示例和解释,方便用户理解和应用。同时,避免使用过于专业的术语,保持语言简洁,让不同水平的用户都能受益。</think>以下是 Golang 的滑动窗口算法模板及常见变式总结: --- ### **滑动窗口模板代码** ```go func slidingWindow(s string) int { left, right := 0, 0 // 左右指针 window := make(map[byte]int) // 窗口数据存储(根据题目调整类型) result := 0 // 结果(可能是长度、数量等) for right < len(s) { c := s[right] // 右侧进入窗口的字符 right++ // 右指针右移 window[c]++ // 更新窗口数据 // 当窗口不满足条件时收缩左边界 for 需要收缩的条件 { // 根据题目定义条件 d := s[left] // 左侧移出窗口的字符 left++ // 左指针右移 window[d]-- // 更新窗口数据 if window[d] == 0 { delete(window, d) } } // 更新结果(可能需要在此处判断是否满足条件) result = max(result, right - left) // 或其他计算方式 } return result } ``` --- ### **常见变式类型(6大类)** #### **1. 固定窗口大小** - **特征**:窗口长度固定为 `k` - **例题**:643. 子数组最大平均数([LeetCode 643](https://leetcode.com/problems/maximum-average-subarray-i/)) ```go func findMaxAverage(nums []int, k int) float64 { sum := 0 for i := 0; i < k; i++ { sum += nums[i] } maxSum := sum for i := k; i < len(nums); i++ { sum += nums[i] - nums[i - k] if sum > maxSum { maxSum = sum } } return float64(maxSum) / float64(k) } ``` #### **2. 最小窗口子串** - **特征**:找到满足条件的最小窗口 - **例题**:76. 最小覆盖子串([LeetCode 76](https://leetcode.com/problems/minimum-window-substring/)) ```go func minWindow(s string, t string) string { need := make(map[byte]int) for i := range t { need[t[i]]++ } left, valid := 0, 0 resStart, minLen := -1, math.MaxInt32 for right := 0; right < len(s); right++ { if need[s[right]] > 0 { valid++ } need[s[right]]-- for valid == len(t) { if right - left + 1 < minLen { minLen = right - left + 1 resStart = left } need[s[left]]++ if need[s[left]] > 0 { valid-- } left++ } } if resStart == -1 { return "" } return s[resStart : resStart + minLen] } ``` #### **3. 最长无重复子串** - **特征**:窗口内元素唯一 - **例题**:3. 无重复字符的最长子串([LeetCode 3](https://leetcode.com/problems/longest-substring-without-repeating-characters/)) ```go func lengthOfLongestSubstring(s string) int { window := make(map[byte]int) left, maxLen := 0, 0 for right := 0; right < len(s); right++ { c := s[right] window[c]++ for window[c] > 1 { d := s[left] window[d]-- left++ } maxLen = max(maxLen, right - left + 1) } return maxLen } ``` #### **4. 计数型窗口** - **特征**:统计满足条件的窗口数量 - **例题**:567. 字符串的排列([LeetCode 567](https://leetcode.com/problems/permutation-in-string/)) ```go func checkInclusion(s1 string, s2 string) bool { need := make(map[byte]int) for i := range s1 { need[s1[i]]++ } left, valid := 0, 0 window := make(map[byte]int) for right := 0; right < len(s2); right++ { c := s2[right] if need[c] > 0 { window[c]++ if window[c] == need[c] { valid++ } } for right - left + 1 >= len(s1) { if valid == len(need) { return true } d := s2[left] if need[d] > 0 { if window[d] == need[d] { valid-- } window[d]-- } left++ } } return false } ``` #### **5. 多指针窗口** - **特征**:需要维护多个指针或复杂状态 - **例题**:930. 和相同的二元子数组([LeetCode 930](https://leetcode.com/problems/binary-subarrays-with-sum/)) ```go func numSubarraysWithSum(nums []int, goal int) int { return atMost(nums, goal) - atMost(nums, goal-1) } func atMost(nums []int, k int) int { if k < 0 { return 0 } left, sum, count := 0, 0, 0 for right := 0; right < len(nums); right++ { sum += nums[right] for sum > k { sum -= nums[left] left++ } count += right - left + 1 } return count } ``` #### **6. 前缀和+滑动窗口** - **特征**:处理负数或需要快速区间计算 - **例题**:325. 和等于 k 的最长子数组长度([LeetCode 325](https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/)) ```go func maxSubArrayLen(nums []int, k int) int { prefixSum := make(map[int]int) prefixSum[0] = -1 sum, maxLen := 0, 0 for i := 0; i < len(nums); i++ { sum += nums[i] if idx, ok := prefixSum[sum - k]; ok { maxLen = max(maxLen, i - idx) } if _, ok := prefixSum[sum]; !ok { prefixSum[sum] = i } } return maxLen } ``` --- ### **关键技巧** 1. **窗口收缩条件**:定义何时移动左指针 2. **数据结构选择**:根据需求选择哈希表、数组或堆 3. **状态维护**:有效管理窗口内的数据状态 4. **边界处理**:特别注意空窗口、单元素窗口等情况 通过组合这些模式,可以解决 90% 以上的滑动窗口问题。建议先从经典题(如 LeetCode 3/76/209/424)开始练习。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值