力扣第288场周赛题解(补题)

emmm,这次去做核酸,回来的时候就只剩12分钟,只写出来了第一题和第三题,掉大分qaq

文章目录

  • 一 .按奇偶性交换后的最大数字
    • 1.题目
    • 2.思路
    • 3.代码
  • 二. 向表达式添加括号后的最小结果
    • 1.题目
    • 2.思路
    • 3.代码
  • 三. K次增加后的最大乘积
    • 1.题目
    • 2.思路
    • 3.代码
  • 四.花园的最大美丽值
    • 1.题目
    • 2.思路
    • 3.代码


一 .按奇偶性交换后的最大数字

1.题目

力扣第288场周赛题解(补题)_第1张图片

2.思路

因为这里是按照数数的奇偶性来交换数字,所以我们可以很简单地就知道把每个数位上的数字分成奇偶两组,依次把大的往前放,但这里注意检查原来此位置的数字是否能够交换,签到题,具体看代码

3.代码

class Solution {
public:
    int largestInteger(int num) {
        string str = to_string(num);
        int ans=0;
        for (int i = 0; i < str.size(); i++) 
            for (int j = str.size()-1; j >= i; j--) 
                if ((str[i] - str[j])%2 == 0 && str[i] < str[j]) 
                    swap(str[i], str[j]);
        for(int i=0;i<str.length();i++){
        	ans*=10;
			ans+=(int)(str[i]-'0');
		}
        return ans;       
    }
};

二. 向表达式添加括号后的最小结果

1.题目

力扣第288场周赛题解(补题)_第2张图片
力扣第288场周赛题解(补题)_第3张图片

2.思路

因为此题给的字符串数据不是挺大的,所以枚举是一个比较容易想到的方法,也算个签到题吧,主要考个API的应用吧
主要就是找到+的位置

然后就是数据大到枚举会爆的时候,我也不会qaq

3.代码

class Solution {
public:
    string minimizeResult(string expression) {
        int plus=0,len=expression.length(),m=INT_MAX;
        string ans;
        for(int i=0;i<len;i++){
            if(expression[i]=='+'){
                plus=i;
                break;
            }
        }
        for(int i=0;i<plus;i++){
            for(int j=plus+1;j<len;j++){
                if(m>sum(expression,i,j,plus)){
                    m=sum(expression,i,j,plus);
                    ans=expression.substr(0,i)+'('+expression.substr(i,plus-i)+'+'+expression.substr(plus+1,j-plus)+')'+expression.substr(j+1,expression.length()-j-1);
                }
            }
        }
        return ans;
    }
    //求和函数,l与r分别代表括号的位置
    int sum(string str,int l,int r,int plus){
        int s=0;
        string n1=str.substr(0,l);
        string n2=str.substr(l,plus-l);
        string n3=str.substr(plus+1,r-plus);
        string n4=str.substr(r+1,str.length()-r-1);
        int num2=stoi(n2),num3=stoi(n3);
        int num1=(n1.size()==0?1:stoi(n1));
        int num4=(n4.size()==0?1:stoi(n4));
        s=num1*(num2+num3)*num4;
        return s;
    }
};

三. K次增加后的最大乘积

1.题目

力扣第288场周赛题解(补题)_第4张图片

2.思路

emmm,,这题的数学证明我不会,但我是通过观察它那个示例输入来得到每次让最小值增加,最后的结果最大的结论

现在就是主要就是每次对最小值进行加1,所以很直观地优先队列的写法,但是由于效率太低了
我们其实可以考虑使用先排序后贪心的写法,具体代码如下

3.代码

//优先队列
class Solution {
    const int div=1e9+7;
public:
    int maximumProduct(vector<int>& nums, int k) {
        long long ans=1;
        priority_queue<int,vector<int>,greater<int>> que;
        for(auto num:nums){
            que.push(num);
        }
        while(k--){
            int n=que.top();
            que.pop();
            que.push(n+1);
        }
        while(!que.empty()){
            int num=que.top();
            ans=ans*num%div;
            que.pop();
        }
        return ans;
    }
};
//排序加贪心
//这个代码来自力扣
class Solution {
    const int MOD = 1e9+7;
public:
    int maximumProduct(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        int n = nums.size();
        //排序后,当前最小值就是nums[0]
        int cnt = 1 , minv = nums[0];
        //利用次最小值与当前最小值的差值贪心地使得当前最小值最大,cnt为最小值的个数
        for(int i=1;i<n&&k>0;i++){
            int gap=nums[i]-minv;
            //将次最小值变成最小值,因此,如果可以的话,前cnt个最小值都要加上次最小值与当前最小值的差值
            if(gap*i<=k){
                k-=gap*i;
                minv=nums[i];
                cnt=i+1;
            }
            else break;
        }
        long long res = 1L;
        if(k>0){
            //如果还有k次操作,首先将剩余的k平分给这cnt个最小值
            minv+=k/cnt;
            k-=(k/cnt)*cnt;
            int idx=0;
            //如果均分后还剩k'>0,无法完全平分给这个cnt个最小值,那么k'个数为minv+1,剩下(cnt-k')个数为minv
            //后面的while循环就都是连乘代码了
            while(k){
                res=(res*(minv+1))%MOD;
                k--;
                idx++;
            }
            while(idx<cnt){
                res=(res*minv)%MOD;
                idx++;
            }
        }else{
            int idx=0;
            while(idx<cnt){
                res=(res*minv)%MOD;
                idx++;
            }
        }
        while(cnt<n){
            res=(res*nums[cnt])%MOD;
            cnt++;
        }
        return (int)res;
    }
};
/*
作者:feng-476
链接:https://leetcode-cn.com/problems/maximum-product-after-k-increments/solution/zhi-jie-tan-xin-by-feng-476-puzy/
*/

四.花园的最大美丽值

1.题目

力扣第288场周赛题解(补题)_第5张图片

2.思路

首先排序数组。一开始,如果花坛已经是 完整的,那么它就永远是完整的了(因为不能拔去)。因此,可以把这些完好的花坛 除去,并统计它们的数量,返回 fcnt×fcnt即可。

否则我们枚举出能够变成完美花坛的数量x,然后把剩下的花坛找一个最大值T_M,,使每个数都不比T_M小

思路来源:[链接](https://leetcode-cn.com/problems/maximum-total-beauty-of-the-gardens/solution/by-newhar-nk6l/)

3.代码

class Solution {
public:
    long long maximumBeauty(vector<int>& flowers, long long newFlowers, int target, int full, int partial) {
        sort(flowers.begin(), flowers.end());
        
        long long n = flowers.size(), sum = 0, fcnt = 0, j = (int)flowers.size() - 1, T = target - 1;
        for(int i : flowers) {
            sum += i;
        }
        
        long long res = 0;
        
        /* flowers 为剩余需要成为 partial 花坛 */
        while(flowers.size() && newFlowers >= 0) {
            /* 数量超过 T 的花坛不需要再种花 */
            while(j >= 0 && flowers[j] > T) {
                sum -= flowers[j];
                j--;
            }
            
            if(j >= 0) {
                /* 双指针 */
                while(T * (j + 1) - sum > newFlowers) {
                    --T;
                    while(j >= 0 && (flowers[j] > T)) {
                        sum -= flowers[j];
                        --j;
                    }
                }
                res = max(res, T * partial + (n - (long long)flowers.size()) * full);
            }
            
            newFlowers -= max(0, target - flowers.back());
            if(j == (int)flowers.size() - 1) {
                sum -= flowers[j];
                j--;
            }
            flowers.pop_back();
        }
        
        /* 所有花坛都是 full */
        if(newFlowers >= 0) {
            res = max(res, n * full);
        }
        return res;
    }
};

你可能感兴趣的:(算法比赛题解,c++,算法,leetcode,数据结构)