ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LeetCode第 71 场双周赛题解

2022-02-06 01:03:19  阅读:116  来源: 互联网

标签:target nums int 题解 sum 双周 num res LeetCode


题目链接白天补

题目描述:给你一个四位整数,让你重排这个整数中的数字然后分成两部分,允许有前导\(0\)。问分成的两部分的十进制表示的和的最小值。

思路:根据题意模拟即可、

时间复杂度:\(O(1)\)

参考代码:

class Solution {
public:
    int minimumSum(int num) {
        string s = to_string(num);
        vector<int>cnt(10 , 0);
        for(auto c : s) cnt[c - '0'] ++;
        int res = 0, dx = 0 , ct = 0;
        for(int i = 0 ; i < 10 ; ++i){
            if(cnt[i] == 0) continue;
            while(cnt[i]){
                if(ct < 2) res += i * 10;
                else res += i;
                --cnt[i];
                ++ct;
            }
        }
        return res;
    }
};

题目描述:给你一个长度为\(n\)的数组\(nums\),和一个分界数\(x\),让你将数组中小于\(x\)的数字放在所有\(x\)的左边且不改变其原来的相对顺序,将数组中大于\(x\)的数字放在所有\(x\)的右边且不改变其原来的相对顺序。

思路:根据题意模拟即可。

时间复杂度:\(O(n)\)

参考代码:

class Solution {
public:
    vector<int> pivotArray(vector<int>& nums, int pivot) {
        vector<int>res , rs;
        int cnt = 0;
        for(auto num : nums){
            if(num < pivot) res.push_back(num);
            else if(num == pivot) ++cnt;
            else rs.push_back(num);
        }
        for(int i = 1 ; i <= cnt ; ++i) res.push_back(pivot);
        for(auto num : rs) res.push_back(num);
        return res;
    }
};

题目描述:自己看题目吧

思路:根据题意,将时间先表示成\(m : s\)的形式其中\(s < 60\),注意可能会存在\(m > 99\)的情况,需要特判。然后表示成\(4\)位,去除前导\(0\)之后计算价值。然后再\(m \neq 0 , s \leq 39\)的情况下表示\(m - 1 : s + 60\)。在算一次价值。二者取最小即可。

时间复杂度:\(O(1)\)

参考代码:

class Solution {
public:
    int minCostSetTime(int startAt, int moveCost, int pushCost, int targetSeconds) {
        auto solve = [&](vector<int>& target){
            reverse(target.begin() , target.end());
            while(target.back() == 0) target.pop_back();
            reverse(target.begin() , target.end());
            int cur = startAt, res = 0;
            for(auto num : target){
                if(num == cur) res += pushCost;
                else res += pushCost + moveCost;
                cur = num;
            }
            return res;
        };
        int m = targetSeconds / 60 , s = targetSeconds % 60;
        if(m > 99) --m , s += 60;
        vector<int>nums(4 , 0);
        auto process = [&](vector<int>& nums , int m ,int s){
            nums[0] = m / 10;nums[1] = m % 10;
            nums[2] = s / 10; nums[3] = s % 10;
            return ;
        };
        process(nums , m , s);
        int res = solve(nums);
        nums = vector<int>(4 , 0);
        if(m && s <= 39){
            --m;s += 60;
            process(nums , m , s);
            res = min(res , solve(nums));
        }
        return res;
    }
};

题目描述:给你一个长度为\(3 * n\)的数组\(nums\),让你删除其中的\(n\)个,对于删除后的数组,定义其前\(n\)个数字的和为\(sum_{first}\),后\(n\)个数字的和为\(sum_{second}\)。求\(sum_{first} - sum_{second}\)的最小值。

思路:显然我们要最小化\(sum_{first}\),最大化\(sum_{second}\)。考虑定义分界点\(n - 1 \leq p < 2 *n\)。区间[0 , p]包含第一部分的所有元素,根据贪心策略需要删除其中\(p - n + 1\)个最大的元素,而区间[p + 1 , 3 * n - 1]包含第二部分的所有元素,根据贪心策略,需要删除其中$2 * n - p - 1 $个最小的元素。考虑如何维护,对于第一部分,使用一个大根堆即可;对于第二部分,我们使用两个multiset a , b分别存储较小的\(2 * n - p - 1\)个元素和较大的\(n\)个元素,若移动分界点对应的元素在a中存在,则直接删除,否则在b中删除该元素,并将a中的最大值加入b中。

时间复杂度:\(O(nlogn)\)

参考代码:

class Solution {
public:
    long long minimumDifference(vector<int>& nums) {
        priority_queue<int>heap;
        long long sum = 0;
        int n = nums.size();
        int m = n / 3;
        for (int i = 0; i < m; ++i) {
            sum += nums[i];
            heap.push(nums[i]);
        }
        multiset<int> a, b;
        for (int i = m; i < n; ++i) {
            if (b.size() < m) {
                sum -= nums[i];
                b.insert(nums[i]);
            }
            else {
                if (*b.begin() >= nums[i]) a.insert(nums[i]);
                else {
                    int dx = *b.begin();
                    a.insert(*b.begin());
                    b.erase(b.begin());
                    b.insert(nums[i]);
                    sum += dx - nums[i];
                }
            }
        }
        long long res = sum;
        for (int i = m; i < 2 * m; ++i) {
            if (a.find(nums[i]) != a.end()) {
                a.erase(a.find(nums[i]));
            }
            else {
                b.erase(b.find(nums[i]));
                int dx = *a.rbegin();
                sum += nums[i] - dx;
                b.insert(dx);
                a.erase(a.find(dx));
            }
            if (nums[i] < heap.top()) {
                sum -= heap.top();
                heap.pop();
                heap.push(nums[i]);
                sum += nums[i];
            }
            res = min(res, sum);
        }
        return res;
    }
};

标签:target,nums,int,题解,sum,双周,num,res,LeetCode
来源: https://www.cnblogs.com/cherish-/p/15865131.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有