classSolution: defmaximumBeauty(self, nums: List[int], k: int) -> int: nums.sort() ans, left = 0, 0 for right, x inenumerate(nums): # 枚舉右端點 while x - nums[left] > k * 2: # 保證窗口內最大值和最小值之差不超過2k left += 1 ans = max(ans, right - left + 1) # 更新答案 return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution { public: intmaximumBeauty(vector<int>& nums, int k){ int n = nums.size(); sort(nums.begin(), nums.end()); int ans = 0, left = 0; for (int right = 0; right < n; right++) { // 枚舉右端點 while (nums[right] - nums[left] > k * 2) { // 保證窗口內最大值和最小值之差不超過2k left++; } ans = max(ans, right - left + 1); // 更新答案 } return ans; } };
方法二:前綴和(Prefix Sum) + 差分陣列(Difference Array)
再來是一個比較直覺的思路,對於 nums 中的每個數 x ,其能轉換成相同數字的範圍為 [x−k,x+k],因此可以對 nums 中的每個數 x ,在 [x−k,x+k] 區間上 +1 。對於值域中的每個數字 i ,其出現的次數為 nums 中能轉換成 i 的數字的個數,即為將所有元素轉換為 i 的子序列之最大長度。
但是這個思路需要使用到 區間加法 ,若枚舉 [x−k,x+k] 區間上的每個數字 i ,對其出現次數進行加法操作,則在最壞情況下,對於每個數字 x,可能都要進行值域大小 M 次的加法操作,因此時間複雜度為 O(nM),其中 M 是值域的大小。
classSolution { public: intmaximumBeauty(vector<int>& nums, int k){ int mx = *max_element(nums.begin(), nums.end()); vector<int> diff(mx + 2); for (int x : nums) { diff[max(x - k, 0)]++; diff[min(x + k + 1, mx + 1)]--; } int ans = 0, s = 0; for (int x : diff) { s += x; ans = max(ans, s); } return ans; } };
寫在最後
Cover photo is generated by @ゴリラの素材屋さん, thanks for their work!