📘 題目敘述
給定一個整數陣列 nums 與一個整數 k,請找出長度恰好為 k 的連續子陣列中,平均值最大的那一個,並回傳該最大平均值。
答案允許誤差在 10^-5 以內。
條件限制
1 ≤ k ≤ nums.length ≤ 10^5-10^4 ≤ nums[i] ≤ 10^4
🧠 解題思路
這題的核心關鍵是:
平均值最大 ⇔ 總和最大(因為長度 k 固定)
問題可以轉換成:在 nums 中找出長度為 k 的連續子陣列,其中總和最大的那一段,最後再用最大總和除以 k 得到最大平均值。
為了避免重複計算每一段長度為 k 的總和,我使用 Sliding Window(滑動視窗) 的想法。
所有變數
sum:目前為止找到的最大子陣列總和nsum:目前滑動視窗(長度為k)的即時總和k:子陣列固定長度x:最後計算出的最大平均值
🪜 主要流程步驟
第一步:計算第一個長度為 k 的子陣列總和
- 先用一個迴圈,把
nums[0] ~ nums[k-1]加起來 - 這個值同時是第一個視窗的總和,也是目前已知的最大總和
sum
第二步:滑動視窗,更新總和
從索引 k 開始一路往右滑動視窗:
- 每次往右移一格:
- 加上 新進來的元素
nums[j] - 減掉 被移出視窗的元素
nums[j - k]
- 加上 新進來的元素
- 得到新的視窗總和
nsum - 用
sum = max(sum, nsum)更新最大總和
這樣每次視窗移動只做 O(1) 的運算,整體時間是線性的。
第三步:計算最大平均值
- 最後把最大總和
sum除以k - 轉成
double回傳即可
💻 程式碼實作
class Solution {
public:
double findMaxAverage(vector<int>& nums, int k) {
int sum = 0;
int nsum = 0;
double x;
for (int i = 0; i < k; i++) {
sum += nums[i];
}
nsum = sum;
for (int j = k; j < nums.size(); j++) {
nsum = nsum + nums[j] - nums[j - k];
sum = max(sum, nsum);
}
x = (double)sum / k;
return x;
}
};