給你一個下標從 0 開始的整數數組
nums
和一個整數k
。
如果子數組中所有元素都相等,則認為子數組是一個 等值子數組 。注意,空數組是 等值子數組 。
從nums
中刪除最多k
個元素后,返回可能的最長等值子數組的長度。
子數組 是數組中一個連續且可能為空的元素序列。
示例 1:
輸入:nums = [1,3,2,3,1,3], k = 3
輸出:3
解釋:最優的方案是刪除下標 2 和下標 4 的元素。
刪除后,nums 等于 [1, 3, 3, 3] 。
最長等值子數組從 i = 1 開始到 j = 3 結束,長度等于 3 。
可以證明無法創建更長的等值子數組。
示例 2:
輸入:nums = [1,1,2,2,1,1], k = 2
輸出:4
解釋:最優的方案是刪除下標 2 和下標 3 的元素。
刪除后,nums 等于 [1, 1, 1, 1] 。
數組自身就是等值子數組,長度等于 4 。
可以證明無法創建更長的等值子數組。
解題思路
1.元素分類: 構建一個哈希表,用來記錄數字中所有出現的元素以及對應的位置
2.設置窗口: 對每個元素,采用滑動窗口去尋找最長的子數組,窗口的左右邊界為[i,j]
3.滑動窗口: 在滑動窗口時,要保證窗口內刪除的元素不能超過k
,超過則把i
向j
移動
4.計算窗口長度: 每滑動一次窗口,就計算一次窗口長度:i-j+1
,并和全局長度進行比較,保留較長的
class Solution {
public:int longestEqualSubarray(vector<int>& nums, int k) {int n=nums.size();//構建哈希表,記錄每個元素的索引unordered_map<int,vector<int>> pos;for(int i=0;i<n;i++){pos[nums[i]].push_back(i);//記錄每個元素的索引}int res=0;//初始化全局最大長度for(auto &[_,vec]:pos){int i=0;//窗口左端點for(int j=0;j<vec.size();j++){//窗口右端點,不停的向右滑動while(vec[j]-vec[i]-(j-i)>k){//每滑動一次就判斷一次i++;}res=max(res,j-i+1);//更新全局最大長度}}return res;}
};
題后學習
假設我們的 unordered_map pos 如下所示:
unordered_map<int, vector<int>> pos = {{1, {0, 2, 4}},{2, {1, 3}},{3, {5}}
};
在這個哈希表中:
鍵 1 對應的值是一個向量 {0, 2, 4}。
鍵 2 對應的值是一個向量 {1, 3}。
鍵 3 對應的值是一個向量 {5}。
嵌套循環代碼
for(auto &[_,vec]:pos){int i=0; // 窗口左端點for(int j=0;j<vec.size();j++)// ...
-
第一次迭代(外層循環處理鍵 1):
vec 引用向量 {0, 2, 4}
i 初始化為0
內層循環將遍歷 {0, 2, 4},j 從0開始,依次為0, 1, 2。 -
第二次迭代(外層循環處理鍵 2):
vec 引用向量 {1, 3}
i 再次初始化為0
內層循環將遍歷 {1, 3},j 從0開始,依次為0, 1。 -
第三次迭代(外層循環處理鍵 3):
vec 引用向量 {5}
i 再次初始化為0
內層循環將遍歷 {5},j 從0開始,但因為只有一個元素,所以只執行一次。