/*
 * 演算法 / Algorithm: 滑動視窗 + unordered_map 計數 (Sliding window + hash map counting).
 * 右指針擴張視窗，unordered_map 記錄每個值在視窗內的頻率；
 * Right pointer grows the window; the map tracks each value's frequency in the window.
 * 當剛加入的值頻率超過 k，就右移左指針縮小視窗，直到合法。
 * When the just-added value exceeds k, shrink from the left until valid.
 * 時間 O(n)，空間 O(n)。Time O(n), space O(n).
 */

#include <vector>          // std::vector 動態陣列 / dynamic array
#include <unordered_map>   // std::unordered_map 雜湊表 / hash map
#include <algorithm>       // std::max 取最大值 / for std::max

class Solution {
public:
    int maxSubarrayLength(std::vector<int>& nums, int k) {
        // unordered_map<int,int>：鍵是元素值，值是它在視窗內的出現次數
        // key = element value, value = its count inside the current window
        std::unordered_map<int, int> count;

        int left = 0;   // 視窗左端點 / left boundary of the window
        int ans  = 0;   // 目前最長合法視窗長度 / best window length so far

        // 用範圍索引讓 right 從 0 掃到最後 / right pointer sweeps left to right
        for (int right = 0; right < (int)nums.size(); ++right) {
            // count[nums[right]]++ 會在鍵不存在時自動建立並初始化為 0，再加 1
            // Indexing a missing key auto-creates it at 0, then ++ makes it 1
            count[nums[right]]++;

            // 只有剛加入的值可能超標；超過 k 就從左邊縮小視窗
            // Only the newly added value can exceed k; if so, shrink from the left
            while (count[nums[right]] > k) {
                // 移除最左元素：對應計數 -1，然後 left 右移
                // Drop the leftmost element: decrement its count, then advance left
                count[nums[left]]--;
                ++left;   // 左端點右移，視窗縮小 / move left boundary rightwards
            }

            // 此刻視窗保證合法；用其長度更新答案 / window is valid; update the answer
            // std::max 回傳兩者中較大者 / std::max returns the larger of the two
            ans = std::max(ans, right - left + 1);
        }

        return ans;   // 回傳最長好子陣列的長度 / return the length of the longest good subarray
    }
};
