leetcode周赛补题 6.25

第107场双周赛补题

6892. 最大字符串配对数目 - 力扣(LeetCode)

思路:暴力模拟

class Solution {
public:
    bool check(string a, string b)
    {
        for(int i = 0; i < 2; i ++ ) if(a[i] != b[1 - i]) return false;
        return true;
    }
    int maximumNumberOfStringPairs(vector<string>& words) {
        int res = 0;
        for(int i = 0; i < words.size(); i ++ ) 
            for(int j = i + 1; j < words.size(); j ++ )
                if(check(words[i], words[j])) res ++ ;
        return res;
    }
};

6895. 构造最长的新字符串 - 力扣(LeetCode)

思路:贪心,找规律推公式

class Solution {
public:
    int longestString(int x, int y, int z) {
        if(x == y) return min(x, y) * 4 + z * 2;
        else return min(x, y) * 4 + z * 2 + 2;
    }
};

6898. 字符串连接删减字母 - 力扣(LeetCode)

思路:dp,f[i, j, k]三维分别表示前i个字符串,首字母以及尾字母,意义是长度的最小值

class Solution {
public:
    const int INF = 0x3f3f3f3f;
    int minimizeConcatenatedLength(vector<string>& words) {
        int n = words.size();
        int f[n][26][26];
        memset(f, 0x3f, sizeof f);
        f[0][words[0][0] - 'a'][words[0].back() - 'a'] = words[0].size();

        for(int i = 1; i < n; i ++ )
        {
            int sz = words[i].size(), x = words[i][0] - 'a', y = words[i].back() - 'a';
            for(int j = 0; j < 26; j ++ )//枚举已连接的字符串的开头
                for(int k = 0; k < 26; k ++ )//枚举末尾
                {
                    //将当前字符串接在前面
                    if(y == j) f[i][x][k] = min(f[i][x][k], f[i - 1][j][k] + sz - 1);
                    else f[i][x][k] = min(f[i][x][k], f[i - 1][j][k] + sz);
                    //将当前字符串接在后面
                    if(x == k) f[i][j][y] = min(f[i][j][y], f[i - 1][j][k] + sz - 1);
                    else f[i][j][y] = min(f[i][j][y], f[i - 1][j][k] + sz);
                }
        }

        int res = INF;
        for(int i = 0; i < 26; i ++ )
            for(int j = 0; j < 26; j ++ )
                res = min(res, f[n - 1][i][j]);

        return res;
    }
};

6468. 统计没有收到请求的服务器数目 - 力扣(LeetCode)

思路:排序后用哈希+双指针,维护当前收到了信息的服务器的数量

class Solution {
public:
    typedef pair<int, int> PII;
    vector<int> countServers(int n, vector<vector<int>>& logs, int x, vector<int>& queries) {
        sort(logs.begin(), logs.end(), [](vector<int> &a, vector<int> &b) {
            return a[1] < b[1];
        });

        int nq = queries.size();
        vector<PII> vec;
        for(int i = 0; i < nq; i ++ ) vec.push_back({queries[i], i});
        sort(vec.begin(), vec.end());

        vector<int> res(nq);
        unordered_map<int, int> mp;//mp[x] 表示服务器 x 在当前区间内收到了几条消息
        int l = 0, r = 0;

        for(auto u : vec)
        {
            while (r < logs.size() && logs[r][1] <= u.first) mp[logs[r][0]] ++ , r ++ ;
            while (l < logs.size() && logs[l][1] < u.first - x)
            {
                int &t = mp[logs[l][0]];
                t -- ;
                if(t == 0) mp.erase(logs[l][0]);
                l ++ ;
            }
            res[u.second] = n - (int)mp.size();
        }

        return res;
    }
};

第351场周赛补题

2748. 美丽下标对的数目 - 力扣(LeetCode)

思路:枚举

class Solution {
public:
    int getpre(int x)
    {
        while (x >= 10) x /= 10;
        return x;
    }
    int getsuf(int x)
    {
        return x % 10;
    }
    int gcd(int a, int b)
    {
        return b ? gcd(b, a % b) : a;
    }
    int countBeautifulPairs(vector<int>& nums) {
        int res = 0;
        int n = nums.size();
        for(int i = 0; i < n; i ++ )
        {
            for(int j = i + 1; j < n; j ++ )
            {
                int a = getpre(nums[i]), b = getsuf(nums[j]);
                if(gcd(a, b) == 1) res ++ ;
            }
        }
        return res;
    }
};

2749. 得到整数零需要执行的最少操作数 - 力扣(LeetCode)

思路:枚举,将题目转化为求num1 - num2 * k 能否拆成k个2的i次方,其中__builtin_popcountll()是用来求该数字在二进制形式下1的个数的库函数

class Solution {
public:
    int makeTheIntegerZero(int num1, int num2) {
        for(long long k = 1; k <= num1 - num2 * k; k ++ )
            if(k >= __builtin_popcountll(num1 - num2 * k))
                return k;
        return -1;
    }
};

2750. 将数组划分成若干好子数组的方式 - 力扣(LeetCode)

思路:划分的方式其实只能在两个1中间选择,我们将每两个1之间的距离求出来就可以得出可以划分的空,然后乘法原理累乘起来就是答案

class Solution {
public:
    typedef long long LL;
    LL mod = 1e9 + 7;
    int numberOfGoodSubarraySplits(vector<int>& nums) {
        LL n = nums.size();
        LL res = 0;
        LL pre = -1;
        LL count = 0;
        for(LL i = 0; i < n; i ++ )
            if(nums[i] == 1)
            {
                count ++ ;
                if(count == 1) pre = i;
                else 
                {
                    if(count == 2) res = (i - pre) % mod;
                    else res = res % mod * (i - pre) % mod;
                    pre = i;
                }
            }
        if(count == 1) return 1;
        else return res % mod;
    }
};

2751. 机器人碰撞 - 力扣(LeetCode)

思路:桟的运用,和行星碰撞差不多

class Solution {
public:
    vector<int> survivedRobotsHealths(vector<int>& positions, vector<int>& healths, string directions) {
        stack<int> st;
        int n = positions.size(), id[n];
        iota(id, id + n, 0);
        sort(id, id + n, [&](const int i, const int j) {
            return positions[i] < positions[j];
        });
        for(int i : id)
        {
            if(directions[i] == 'R')
            {
                st.push(i);
                continue;
            }

            while (!st.empty())
            {
                int top = st.top();
                if(healths[top] > healths[i])
                {
                    healths[top] -- ;
                    healths[i] = 0;
                    break;
                }
                if(healths[top] == healths[i])
                {
                    healths[top] = 0;
                    healths[i] = 0;
                    st.pop();
                    break;
                }
                if(healths[top] < healths[i])
                {
                    healths[top] = 0;
                    st.pop();
                    healths[i] -- ;
                }
            }
        }

        healths.erase(remove(healths.begin(), healths.end(), 0), healths.end());

        return healths;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值