1. 程式人生 > 其它 >LeetCode第 288 場周賽題解

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;
    }
};