LeetCode第 288 场周赛题解
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;
}
};
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。