classSolution: defminIncrementForUnique(self, nums: List[int]) -> int: n = len(nums) nums.sort() ans = 0 for i inrange(1, n): if nums[i] <= nums[i-1]: ans += nums[i-1] + 1 - nums[i] nums[i] = nums[i-1] + 1 return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution { public: intminIncrementForUnique(vector<int>& nums){ int n = nums.size(), ans = 0; sort(nums.begin(), nums.end()); for (int i = 1; i < n; i++) { if (nums[i] <= nums[i-1]) { ans += nums[i-1] + 1 - nums[i]; nums[i] = nums[i-1] + 1; } } return ans; } };
維護一個長度為 2×105 的陣列 cnt,其中 cnt[i] 表示數字 i 出現的次數。遍歷值域中的每個數字 x ,x 出現次數大於 1,則代表有 cnt[x]−1 個 x 需要被調整成更大的數字,因此先把這些多餘的數字加到一個陣列 left 中。當遇到下一個數字時,如果該數字沒有出現過,則可以從 left 中取出一個多餘的數字,將其調整到當前數字,並將答案加上需要的操作次數。
classSolution: defminIncrementForUnique(self, nums: List[int]) -> int: n = len(nums) mx = max(nums) cnt = [0] * (mx + n) for x in nums: cnt[x] += 1 ans = 0 left = [] for x inrange(mx + n): if cnt[x] >= 2: left.extend([x] * (cnt[x] - 1)) elif left and cnt[x] == 0: ans += x - left.pop() return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution { public: intminIncrementForUnique(vector<int>& nums){ int n = nums.size(), mx = *max_element(nums.begin(), nums.end()); vector<int> cnt(mx + n, 0), left; for (int x : nums) cnt[x]++; int ans = 0; for (int x = 0; x < mx + n; x++) { if (cnt[x] >= 2) { left.insert(left.end(), cnt[x] - 1, x); } elseif (!left.empty() && cnt[x] == 0) { ans += x - left.back(); left.pop_back(); } } return ans; } };
方法二優化
在方法二中,我們需要使用一個陣列 left 來存放多餘的數字,使得在每次遇到新的數字時,需要從 left 中取出一個數字。這裡可以進一步優化,不需要使用 left 陣列,只需要維護一個整數 left_cnt 來表示多餘的數字個數即可。
由於枚舉到沒有出現過的數字 x 時,需要從 left 中取出一個數字 y,將 y 調整到 x,此時需要的操作次數為 x−y 。可以看出若 cnt[y]≥2 ,則其對答案的貢獻為 −y×(cnt[y]−1),因此可以提前計算 y 的貢獻,並將其加到答案中。如此便不用維護 left 陣列。
classSolution: defminIncrementForUnique(self, nums: List[int]) -> int: n = len(nums) mx = max(nums) cnt = [0] * (mx + n) for x in nums: cnt[x] += 1 ans = 0 left = 0 for x inrange(mx + n): if cnt[x] >= 2: left += cnt[x] - 1 ans -= x * (cnt[x] - 1) elif left > 0and cnt[x] == 0: ans += x left -= 1 return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { public: intminIncrementForUnique(vector<int>& nums){ int n = nums.size(), mx = *max_element(nums.begin(), nums.end()); vector<int> cnt(mx + n, 0); for (int x : nums) cnt[x]++; int ans = 0, left = 0; for (int x = 0; x < mx + n; x++) { if (cnt[x] >= 2) { left += cnt[x] - 1; ans -= x * (cnt[x] - 1); } elseif (left > 0 && cnt[x] == 0) { ans += x; left--; } } return ans; } };
寫在最後
Cover photo is generated by @ゴリラの素材屋さん, thanks for their work!