Leetcode 双周赛 41 题解

1684. 统计一致字符串的数目

简单模拟

class Solution {
public:
    int countConsistentStrings(string allowed, vector<string>& words) {
            int n = words.size(),num = 0;
            int hash[30];
            memset(hash,0,sizeof hash);
            for(int i = 0;i < allowed.size(); i ++) hash[allowed[i] - 'a'] ++;
            for(int i = 0 ;i < n ;i ++){
                int flag = 0;
                for(int j = 0 ; j < words[i].size(); j++){
                    if(!hash[words[i][j] - 'a']){
                        flag = 1;
                        break;
                    }
                }
                if(!flag) num ++;
            }
            return num;
    }
};

1685. 有序数组中差绝对值之和

简单思维

class Solution {
public:
    vector<int> getSumAbsoluteDifferences(vector<int>& nums) {
        int n = nums.size();
        vector<int> s(n + 1);
        vector<int> r(n);
        for(int i = 1; i <= n ;i ++) s[i] = s[i-1] + nums[i-1];
        for(int i = 0;i < n ;i ++){
            r[i] = (i - 0 - (n - 1 - i)) * nums[i] - s[i] + s[n] - s[i+1];
        }
        return r;
    }
};

1686. 石子游戏 VI

贪心

将两组石头的价值合并,每次取价值最大的那一组。

class Solution {
public:
    struct nod{
        int a,b;
    }node[100000 + 10];
    static bool cmp(nod x,nod y){
        return x.a + x.b > y.a + y.b;
    }
    int stoneGameVI(vector<int>& x, vector<int>& y) {
        for(int i = 0; i < x.size(); i ++){
            node[i].a = x[i];
            node[i].b = y[i];
        }
        int flag,numa = 0,numb = 0;
        sort(node,node+x.size(),cmp);
        for(int i = 0;i < x.size(); i ++){
            if(i&1){
                numb += node[i].b;
            }else{
                numa += node[i].a;
            }
        }
        if(numa > numb) flag = 1;
        else if(numa == numb) flag = 0;
        else flag = -1;
        return flag;
    }
};

1687. 从仓库到码头运输箱子

单调队列优化

class Solution {
public:
    int n; // 总个数
    vector<int> s; // 前缀和数组

    // 计算把(l, r]区间里的货物运出去所花费的段数
    int cost(int l, int r) {
        // 如果左端点l + 1是起始点的话,那么段数是分界点数
        if (s[l + 1] != s[l])
            return s[r] - s[l];
        // 如果左端点不是分界点的话,那么段数就是分界点数+1
        return s[r] - s[l] + 1;
    }

    int boxDelivering(vector<vector<int>>& boxes, int portsCount, int maxBoxes, int maxWeight) {
        n = boxes.size();
        s.resize(n + 2);
        // 求前缀和数组
        for (int i = 1; i <= n; i ++ ) {
            s[i] = s[i - 1];
            // 这里要看一下i是不是分界点,每到分界点就+1
            if (i == 1 || boxes[i - 1][0] != boxes[i - 2][0])
                s[i] ++ ;
        }

        // dp的数组
        vector<int> f(n + 1);
        // 双端队列
        deque<int> q;
        q.push_back(0);
        // 从前往后遍历每个位置i
        // j是满足约束能装填货物的最靠前的位置(j-1到i就不能装进去了)
        // w是当前货物的总重量
        for (int i = 1, j = 1, w = 0; i <= n; i ++ ) {
            // 把第i个箱子的重量加进来
            w += boxes[i - 1][1];
            // 因为i往前移动了,如果不满足约束就一直把j往前移动,前面的货物滑动出去
            while (w > maxWeight || i - j + 1 > maxBoxes) {
                w -= boxes[j - 1][1];
                j ++ ;
            }
            // 同时在队列里把滑出队列的删除掉
            while (q.front() < j - 1)
                q.pop_front();
            // 当前的k
            int k = q.front();
            // dp计算,注意要加上回程时候的1
            f[i] = f[k] + cost(k, i) + 1;
            // 单调队列优化,当队尾比队头还差的时候就不停删除队尾
            while (
            q.size() &&
            f[q.back()] >= f[i] + cost(i, i + 1) - cost(q.back(), i + 1)
                  )
                q.pop_back();
            // 将当前的i入队
            q.push_back(i);
        }
        return f[n];
    }
};
原文地址:https://www.cnblogs.com/DWVictor/p/14155659.html