LeetCode第 288 場周賽題解
阿新 • • 發佈:2022-04-10
6037. 按奇偶性交換後的最大數字
題目描述:給你一個正整數 num
。你可以交換 num
中 奇偶性 相同的任意兩位數字(即,都是奇數或者偶數)。返回交換 任意 次之後 num
的 最大 可能值。
思路:將奇偶分開排序後貪心即可。
時間複雜度:\(O(nlogn)\) , \(n\)為數字num
的位數
參考程式碼:
class Solution { public: int largestInteger(int num) { vector<int>cnt(10 , 0); string s = to_string(num); vector<int>even , odd; for(auto&& c : s){ int val = c - '0'; if(val & 1) even.push_back(val); else odd.push_back(val); } sort(even.begin() , even.end()); sort(odd.begin() , odd.end()); int p = (int)even.size() - 1 , q = (int)odd.size() - 1; int res = 0; for(int i = 0 ; i < s.size() ; ++i){ int val = s[i] - '0'; if(val & 1) res = res * 10 + even[p--]; else res = res * 10 + odd[q--]; } return res; } };
6038. 向表示式新增括號後的最小結果
題目描述:給你一個加法算式,讓你在加號兩邊新增括號,問加括號之後整個算式取得最小值時的表示式是什麼。
思路:考慮到表示式長度比較小,所以找到加號的位置之後暴力列舉括號的位置即可。
時間複雜度:\(O(n^3)\),\(n\)為表示式的長度。
參考程式碼:
class Solution { public: string minimizeResult(string e) { int idx = 0 , n = e.size(); while(e[idx] != '+') ++idx; string res; int mx = INT_MAX; for(int i = 0 ; i <= idx - 1; ++i){ for(int j = idx + 1 ; j < n ; ++j){ int cur = 0, cnt = 0; for(int k = 0 ; k < i ; ++k) cnt = cnt * 10 + e[k] - '0'; if(cnt == 0) cnt = 1; cur = cnt; int lr = 0 , rs = 0; for(int k = i ; k < idx ; ++k) lr = lr * 10 + e[k] - '0'; for(int k = idx + 1 ; k <= j ; ++ k) rs = rs * 10 + e[k] - '0'; cur = cur * (lr + rs); cnt = 0; for(int k = j + 1 ; k < n ; ++k) cnt = cnt * 10 + e[k] - '0'; if(cnt == 0) cnt = 1; cur *= cnt; if(cur < mx){ mx = cur; res.clear(); for(int k = 0 ; k < n ; ++k){ if(k == i) res += '('; res += e[k]; if(k == j) res += ')'; } } } } return res; } };
6039. K 次增加後的最大乘積
題目描述:給你一個數組和一個整數\(k\),你可以從陣列中選出一個數,然後對它執行+1
操作,總共的操作次數不超過k
,問最後陣列所有元素的乘積的最大值是多少?答案對1e9+7
取模。
思路:比較明顯的貪心,每次選取最小的數字對其執行+1
操作即可。
時間複雜度:\(O(nlogn)\)
參考程式碼:
class Solution { public: int maximumProduct(vector<int>& nums, int k) { priority_queue<int , vector<int> , greater<int>>heap; for(auto&& num : nums) heap.push(num); while(k--){ int dx = heap.top();heap.pop(); heap.push(dx + 1); } int res = 1; const int mod = 1e9 + 7; while(!heap.empty()){ int dx = heap.top();heap.pop(); res = 1ll * res * dx % mod; } return res; } };
6040. 花園的最大總美麗值
題目描述:有\(n\)個花園,若一個花園種的花的數量不少於target
,則可獲得full
點價值,若所有種的花的數量少於target
的花園中,種的花的最小數目是x
,那麼可以獲得\(x \times partial\)點價值。現在這\(n\)個花園中已經種了一些花,你總共額外可以種newFlowers
朵,問你最終獲得的價值的最大值是多少。
思路:我們先對花園按照種的花的數量進行逆序排序,然後順序列舉,若列舉到\(i\),表示前\(i\)個花園中種的花的數量都至少為target
,對於剩下的花園,考慮二分其最小值,然後使用樹狀陣列去求滿足最小值需要的花的數量進行檢驗即可。
時間複雜度:\(O(nlog^2n)\)
參考程式碼:
class Solution {
public:
long long maximumBeauty(vector<int>& flowers, long long allf, int target, int full, int partial) {
long long res = 0, sum = 0;
multiset<int> s;
const int N = 1e5 + 5;
vector<long long> tr(100005 , 0);
vector<long long>tridx(N , 0);
for(auto&& flower : flowers){
if(flower >= target) sum += full;
else s.insert(flower);
}
auto lowbit = [](int x){return x &-x;};
auto add = [&](vector<long long>& tr , int idx , int val){
while(idx < N){
tr[idx] += val;
idx += lowbit(idx);
}
return ;
};
auto getsum = [&](vector<long long>& tr , int idx)->long long{
long long ans = 0;
while(idx != 0){
ans += tr[idx];
idx -= lowbit(idx);
}
return ans;
};
vector<int>nums;
for(auto&& val : s){
add(tr , val , val);
add(tridx , val , 1);
nums.push_back(val);
}
nums.push_back(target);
reverse(nums.begin() , nums.end());
int n = nums.size();
res = sum;
for(int i = 0 ; i < n ; ++i){
int dx = target - nums[i];
if(i != 0)add(tr , nums[i] , -nums[i]);
if(i != 0)add(tridx , nums[i] , -1);
allf -= dx;
if(allf < 0) break;
if(i != 0) sum += full;
if(i == n - 1) break;
int lr = 1 , rs = target - 1, pos = 0;
while(lr <= rs){
int mid = lr + rs >> 1;
int cnt = getsum(tridx , mid);
long long tmpsum = getsum(tr , mid);
long long need = 1ll * cnt * mid - tmpsum;
if(need <= allf) lr = mid + 1 , pos = mid;
else rs = mid - 1;
}
res = max(res , sum + 1ll * pos * partial);
}
res = max(res , sum);
return res;
}
};