# Weekly Contest 429
日期 2024/12/22
第三題沒時間想出來,討論區是使用 binary search 猜一個數字,並驗證這個數字是否可行。
- [Minimum Number of Operations to Make Elements in Array Distinct](https://leetcode.com/problems/minimum-number-of-operations-to-make-elements-in-array-distinct/)
- [Maximum Number of Distinct Elements After Operations](https://leetcode.com/problems/maximum-number-of-distinct-elements-after-operations/)
- [Smallest Substring With Identical Characters I](https://leetcode.com/problems/smallest-substring-with-identical-characters-i/)
- [Smallest Substring With Identical Characters II](https://leetcode.com/problems/smallest-substring-with-identical-characters-ii/)
### 第一題
```cpp
int minimumOperations(vector<int>& nums) {
unordered_map<int, int> freq;
for(int x: nums)
freq[x]++;
int ret = 0;
const int n = nums.size();
int i = 0;
auto check = [&freq]() {
for(auto kv: freq) {
if(kv.second > 1)
return false;
}
return true;
};
if(check())
return 0;
while(i < n) {
if(i + 2 < n) {
freq[nums[i]]--;
freq[nums[i + 1]]--;
freq[nums[i + 2]]--;
ret++;
i = i + 3;
}else{
for(int j = i; j < n; j++)
freq[nums[j]]--;
ret++;
i = n;
}
if(check())
return ret;
}
return ret;
}
```
### 第二題
`mmin` 用於記錄最小可使用數值,避免重複計算(不這樣做會 TLE)
```cpp
int maxDistinctElements(vector<int>& nums, int k) {
const int n = nums.size();
unordered_set<int> used;
sort(nums.begin(), nums.end());
int mmin = nums[0] - k;
for (int i = 0; i < n;) {
int count = 0;
while(i + count < n && nums[i] == nums[i + count])
count++;
int x = nums[i];
i += count;
int start = max(x - k, mmin);
while(count--) {
while(start <= x + k) {
auto it = used.insert(start);
start++;
if(it.second) {
// cout << x + k << " ";
break;
}
}
}
mmin = max(mmin, start);
}
return used.size();
}
```
### 第三題
https://leetcode.com/problems/smallest-substring-with-identical-characters-i/solutions/6172678/binary-search-with-special-case-for-mid-1
```cpp
bool check(string& s, int numOps, char startChar) {
for (int i = 0; i < s.size(); i++) {
if (startChar == s[i])
numOps--;
startChar = !(startChar - '0') + '0';
}
return numOps >= 0;
}
bool isValid(string& s, int numOps, int mid) {
if (mid == 1)
return check(s, numOps, '1') || check(s, numOps, '0');
int count = 0;
for (int i = 0, last = -1; i < s.size(); i++) {
if (s[i] == last)
count++;
else {
numOps -= count / (mid + 1);
last = s[i];
count = 1;
}
}
if (count > mid)
numOps -= count / (mid + 1);
return numOps >= 0;
}
int minLength(string s, int numOps) {
int start = 1;
int end = s.size();
int ret = s.size();
while (start <= end) {
int mid = (start + end) / 2;
if (isValid(s, numOps, mid)) {
ret = mid;
end = mid - 1;
} else
start = mid + 1;
}
return ret;
}
```
### 第四題
與第三題相同