其他分享
首页 > 其他分享> > 11.16

11.16

作者:互联网

1658. 将 x 减到 0 的最小操作数

难度中等18

给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1

示例 1:

输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。

示例 2:

输入:nums = [5,6,7,8,9], x = 4
输出:-1

示例 3:

输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。

提示:

解答:前缀和,后缀和,两数之和

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        unordered_map<int, int>cnt;
        cnt[0] = -1;
        int sum = 0;
        int res = INT_MAX;
        for(int i = 0; i < nums.size(); i++){
            sum += nums[i];
            cnt[sum] = i;
        }
        if(cnt.find(x) != cnt.end())res = min(res, cnt[x] + 1);
        sum = 0;
        for(int i = nums.size() - 1; i >= 0; i--){
            sum += nums[i];
            if(cnt.find(x - sum) != cnt.end()){
                int ans = nums.size() - i + cnt[x - sum] + 1;
                if(ans > nums.size())continue;
                res = min(res, ans);
            }
        }
        return res == INT_MAX? -1 : res;
    }
};

1423. 可获得的最大点数

难度中等31

几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。

每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。

你的点数就是你拿到手中的所有卡牌的点数之和。

给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。

示例 1:

输入:cardPoints = [1,2,3,4,5,6,1], k = 3
输出:12
解释:第一次行动,不管拿哪张牌,你的点数总是 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 。

示例 2:

输入:cardPoints = [2,2,2], k = 2
输出:4
解释:无论你拿起哪两张卡牌,可获得的点数总是 4 。

示例 3:

输入:cardPoints = [9,7,7,9,7,7,9], k = 7
输出:55
解释:你必须拿起所有卡牌,可以获得的点数为所有卡牌的点数之和。

示例 4:

输入:cardPoints = [1,1000,1], k = 1
输出:1
解释:你无法拿到中间那张卡牌,所以可以获得的最大点数为 1 。 

示例 5:

输入:cardPoints = [1,79,80,1,1,1,200,1], k = 3
输出:202

提示:

解答:还是前缀和思想,计算前面hash[i] + cnt[k - i]和的最大值

class Solution {
public:
    int maxScore(vector<int>& nums, int k) {
        int res = 0;
        unordered_map<int, int>hash,cnt;
        int sum = 0;
        hash[0] = 0;
        cnt[0] = 0;
        for(int i = 0; i < nums.size(); i++){
            sum += nums[i];
            hash[i + 1] = sum;
        }
        sum = 0;
        for(int i = nums.size() - 1, j = 0; i >= 0; i--, j++){
            sum += nums[i];
            cnt[j + 1] = sum;
        }
        for(int i = 0; i <= k; i++){
            res = max(res, hash[i] + cnt[k - i]);
        }
        return res;
    }
};

406. 根据身高重建队列

难度中等627

假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。

注意:
总人数少于1100人。

示例

输入:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]

输出:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]

解答:排序二分,树状数组

class Solution {
public:
    int n;
    vector<int> tr;

    int lowbit(int x) {
        return x & -x;
    }

    void add(int x, int v) {
        for (int i = x; i <= n; i += lowbit(i)) tr[i] += v;
    }

    int query(int x) {
        int res = 0;
        for (int i = x; i; i -= lowbit(i)) res += tr[i];
        return res;
    }

    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        n = people.size();
        tr.resize(n + 1);

        sort(people.begin(), people.end(), [](vector<int>a, vector<int>b) {
            if (a[0] != b[0]) return a[0] < b[0];
            return a[1] > b[1];
        });

        vector<vector<int>> res(n);
        for (auto p: people) {
            int h = p[0], k = p[1];
            int l = 1, r = n;
            while (l < r) {
                int mid = l + r >> 1;
                if (mid - query(mid) >= k + 1) r = mid;
                else l = mid + 1;
            }
            res[r - 1] = p;
            add(r, 1);
        }
        return res;
    }
};

标签:cnt,nums,11.16,res,sum,int,点数
来源: https://www.cnblogs.com/domy/p/13986308.html