【LeetCode周赛】第 384 场周赛

目录

  • [3033. 修改矩阵 简单](#3033. 修改矩阵 简单)
  • [3034. 匹配模式数组的子数组数目 I 中等](#3034. 匹配模式数组的子数组数目 I 中等)
  • [3035. 回文字符串的最大数量 中等](#3035. 回文字符串的最大数量 中等)
  • [3036. 匹配模式数组的子数组数目 II 困难](#3036. 匹配模式数组的子数组数目 II 困难)

3033. 修改矩阵 简单

3033. 修改矩阵

分析:

获取每一列的最大元素,将矩阵中的 -1 替换成每一列的最大元素。

代码:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> modifiedMatrix(vector<vector<int>>& matrix) {
        int m=matrix.size(), n=matrix[0].size();
        vector<int> x,y;
        for(int i=0;i<n;i++){
            int t = -1;
            x.clear(),y.clear();
            for(int j=0;j<m;j++){
                if(matrix[j][i]==-1) x.push_back(j),y.push_back(i);
                else t=max(t,matrix[j][i]);
            }
            for(int k=0;k<x.size();k++){
                matrix[x[k]][y[k]]=t;
            }
        }
        return matrix;
    }
};

3034. 匹配模式数组的子数组数目 I 中等

3034. 匹配模式数组的子数组数目 I

分析:

根据 nums 中各个元素的值,计算得到其对应的 匹配模式数组 nums_pattern

再在 nums_pattern 中寻找子数组 pattern 的数量。

代码:

cpp 复制代码
class Solution {
public:
    int countMatchingSubarrays(vector<int>& nums, vector<int>& pattern) {
        int n=nums.size(), m=pattern.size(), ans=0;
        vector<int> cnt;
        for(int i=1;i<n;i++){
            if(nums[i]>nums[i-1]) cnt.push_back(1);
            else if(nums[i]==nums[i-1]) cnt.push_back(0);
            else cnt.push_back(-1);
        }
        for(int i=0;i<cnt.size()-m+1;i++){
            for(int j=0;j<m;j++){
                if(cnt[i+j]!=pattern[j]) break;
                if(j==m-1) ans++;
            }
        }
        return ans;
    }
};

3035. 回文字符串的最大数量 中等

3035. 回文字符串的最大数量

分析:

题目求的是最终为回文字符串的数量,并非最小的交换次数,因此转换思维直接 构造 回文字符串。

  • 首先统计所有字符串中各个小写字母的出现次数,同时记录各个字符串的长度。
  • 对字符串长度数组进行升序排序(构造长的回文字符串时,可能会导致多个短的字符串构不成回文字符串)。
  • 利用贪心思维构造回文字符串
    • 正常情况下,一次直接填入偶数个字符保证字符串为回文字符串。
    • 如果字符串长度为奇数,不能填入偶数字符时,计数数组 cnt 中寻找是否有剩余次数为奇数的字符,否则返回还没使用完的字符。
  • 对于 能直接使用偶数字符对填充完毕 ,或者 剩一个字符的字符串,最终都能构成回文字符串,此时数量 +1。最终即为回文字符串的最大数量。

代码:

cpp 复制代码
class Solution {
public:
    int findOdd(int cnt[]){
        int ans=-1;
        for(int i=0;i<26;i++){
            if(cnt[i]%2==1) return i;
            else if(cnt[i]>0) ans=i;
        }
        return ans;
    }

    int maxPalindromesAfterOperations(vector<string>& words) {
        int cnt[26], ans=0;memset(cnt, 0, sizeof(cnt));
        vector<int> t;
        for(auto word : words){
            for(auto i : word){
                cnt[i - 'a']++;
            }
            t.push_back(word.length());
        }
        sort(t.begin(), t.end());
        for(int i : t){
            int tmp = i;
            for(int j=0;j<26&&tmp>1;j++){
                int tt = tmp/2,tc = cnt[j]/2;
                if(tt*2<=cnt[j]){
                    tmp-=tt*2;
                    cnt[j]-=tt*2;
                }else{
                    tmp-=tc*2;
                    cnt[j]-=tc*2;
                }
            }
            if(tmp==0){ans++;continue;}
            if(tmp==1){
                cnt[findOdd(cnt)]--;ans++;}
            else{
                int j=0;
                while(tmp){
                    if(cnt[j]>0){
                        if(cnt[j]>=tmp) cnt[j]-=tmp,tmp=0;
                        else tmp-=cnt[j],cnt[j]=0;
                    }
                    j++;
                }
            }
        }
        return ans;
    }
};

更加巧妙方法:利用位运算。

cpp 复制代码
class Solution {
public:
    int maxPalindromesAfterOperations(vector<string>& words) {
        int ans = 0, tot = 0, mask = 0;
        for (auto &w : words) {
            tot += w.length();
            for (char c : w) {
                mask ^= 1 << (c - 'a'); // 对于出现奇数次的字符,对应位为1,否则为0
            }
        }
        tot -= __builtin_popcount(mask); // 减去无法构成相同字符对的字符(单个的字符)
        cout<<tot<<endl;
        ranges::sort(words, [](const auto &a, const auto &b) {
            return a.length() < b.length();
        });
        for (auto &w : words) {
            tot -= w.length() / 2 * 2; // 长度为奇数的字符串,不考虑中间的单个字符
            if (tot < 0) break; // 如果相同字符对无法构建剩下的回文字符串,则跳出循环,此即为回文字符串的最大数量
            ans++;
        }
        return ans;
    }
};

3036. 匹配模式数组的子数组数目 II 困难

3036. 匹配模式数组的子数组数目 II

分析:

根据 nums 中各个元素的值,计算得到其对应的 匹配模式数组 nums_pattern

再在 nums_pattern 中寻找子数组 pattern 的数量,即数组的模式匹配,可以利用 KMP算法 解决。

代码:

cpp 复制代码
class Solution {
public:
    int countMatchingSubarrays(vector<int>& nums, vector<int>& pattern) {
        int n=nums.size(), m=pattern.size(), ans=0;
        vector<int> cnt, ne(m);
        for(int i=1;i<n;i++){
            if(nums[i]>nums[i-1]) cnt.push_back(1);
            else if(nums[i]==nums[i-1]) cnt.push_back(0);
            else cnt.push_back(-1);
        }
        ne[0]=-1;
        for(int i=1,j=-1;i<m;i++){
            while(j!=-1&&pattern[i]!=pattern[j+1]) j=ne[j];
            if(pattern[i]==pattern[j+1]) j++;
            ne[i]=j;
        }
        for(int i=0,j=-1;i<n-1;i++){
            while(j!=-1&&cnt[i]!=pattern[j+1]) j=ne[j];
            if(cnt[i]==pattern[j+1]) j++;
            if(j==m-1){
                ans++;
                j=ne[j];
            }
        }
        return ans;
    }
};
相关推荐
江畔柳前堤8 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore9 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考10 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX11 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面12 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号12 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽12 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI12 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者14 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者14 小时前
【征程6】校准量化中HistogramObserver解析
算法