Leetcode - 周赛434

news2025/2/5 22:37:17

目录

  • 一、3432. 统计元素和差值为偶数的分区方案
  • 二、3433. 统计用户被提及情况
  • 三、3434. 子数组操作后的最大频率
  • 四、3435. 最短公共超序列的字母出现频率

一、3432. 统计元素和差值为偶数的分区方案

题目链接
在这里插入图片描述
本题可以直接模拟,这里再介绍一个数学做法,假设 n u m s [ : i ] nums[:i] nums[:i] 的和为 L L L n u m s [ : ] nums[:] nums[:] 的和为 S S S,那么 n u m s [ i + 1 : ] nums[i+1:] nums[i+1:] 的和为 S − L S-L SL,题目要求满足 a b s ( L − ( S − L ) ) abs(L-(S-L)) abs(L(SL)) 为偶数,化简一下得到 2 ∗ L − S 2*L-S 2LS,可以发现差值是否为偶数和怎么划分无关,只和 S S S 有关,而 S S S 是固定的(数组的和),所以只要 S S S 为偶数,那么方案数为 l e n ( n u m s ) − 1 len(nums)-1 len(nums)1,否则方案数为 0 0 0

代码如下:

class Solution {
    public int countPartitions(int[] nums) {
        int s = 0;
        for(int x : nums){
            s += x;
        }
        return s%2 == 0 ? nums.length-1 : 0;
    }
}
//模拟做法
class Solution {
    public int countPartitions(int[] nums) {
        int n = nums.length;
        int s = 0;
        for(int x : nums){
            s += x;
        }
        int ans = 0;
        int p = 0;
        for(int i=0; i<n-1; i++){
            int x = nums[i];
            p += x;
            if((s-p-p)%2 == 0)
                ans++;
        }
        return ans;
    }
}

二、3433. 统计用户被提及情况

题目链接
在这里插入图片描述
本题就是一道模拟题,唯一要注意的就是在排序的时候,如果离线事件和消息时间同时发生,优先处理离线事件。

代码如下:

class Solution {
    public int[] countMentions(int n, List<List<String>> events) {
        int[] ans = new int[n];
        Collections.sort(events, (x, y)->{
            int t = Integer.parseInt(x.get(1))-Integer.parseInt(y.get(1));
            return t==0?y.get(0).compareTo(x.get(0)):t;    
        });
        //使用time数组记录每个用户下一次上线的时间
        int[] time = new int[n];
        for(List<String> x : events){
            String s = x.get(0);
            int t = Integer.parseInt(x.get(1));
            String y = x.get(2);
            if(s.equals("MESSAGE")){
                if(y.equals("ALL")){
                    for(int i=0; i<n; i++){
                        ans[i]++;
                    }
                }else if(y.equals("HERE")){
                    for(int i=0; i<n; i++){
                        if(time[i] <= t){
                            ans[i]++;
                        }
                    }
                }else{
                    for(String c : y.split(" ")){
                        int j = Integer.parseInt(c.substring(2));
                        ans[j]++;
                    }
                }
            }else{
                for(String c : y.split(" ")){
                    int j = Integer.parseInt(c);
                    time[j] = t + 60;
                }
            }
        }
        return ans;
    }
}

三、3434. 子数组操作后的最大频率

题目链接
在这里插入图片描述
本题可以将 n u m s nums nums 数组分成三个部分:被修改的子数组的左边,被修改的子数组,被修改的子数组的右边,考虑将 n u m s nums nums 中等于 t a r g e t target target 的元素变成 k k k,我们可以定义以下三种状态:

  • f [ i + 1 ] [ 0 ] f[i+1][0] f[i+1][0]:表示被修改的子数组的左边,即统计 n u m s [ : i ] nums[:i] nums[:i] 中等于 k k k 的元素个数。
  • f [ i + 1 ] [ 1 ] f[i+1][1] f[i+1][1]:表示被修改的子数组 + 左边,即被修改的子数组以 i i i 结尾时 k k k 出现的最大频率。
  • f [ i + 1 ] [ 2 ] f[i+1][2] f[i+1][2]:表示被修改的子数组 + 左边 + 右边,即被修改的子数组以 < i < i <i 的下标结尾时 k k k 出现的最大频率。
  • 注:这三种状态都表示 n u m s [ : i ] nums[:i] nums[:i] k k k 出现的最大频率,只不过表示的范围不同!!!
  • 显然,假设被修改子数组的范围是 [ i , j ] [i,j] [i,j] j j j 当然可以是 n − 1 n-1 n1,也可以是 < n − 1 < n-1 <n1,所以 a n s = m a x ( a n s , f [ n ] [ 1 ] , f [ n ] [ 2 ] ) ans=max(ans,f[n][1],f[n][2]) ans=max(ans,f[n][1],f[n][2])

从左到右遍历 n u m s nums nums,设 x = n u m s [ i ] x = nums[i] x=nums[i],考虑转移来源:

  • 【左】只能从【左】转移过来, f [ i + 1 ] [ 0 ] f[i+1][0] f[i+1][0] 只能从 f [ i ] [ 0 ] f[i][0] f[i][0] 转移过来,即 f [ i + 1 ] [ 0 ] = f [ i ] [ 0 ] + ( x = = k ? 1 : 0 ) f[i+1][0] = f[i][0]+(x==k?1:0) f[i+1][0]=f[i][0]+(x==k?1:0),(PS:实际上就是计算 k k k 的出现次数,可以使用一个变量来表示)
  • 【左 + 中】可以从【左】或者【左 + 中】转移过来,如果 x = = t a r g e t x == target x==target f [ i + 1 ] [ 1 ] = m a x ( f [ i ] [ 0 ] , f [ i ] [ 1 ] ) + 1 f[i+1][1]=max(f[i][0],f[i][1])+1 f[i+1][1]=max(f[i][0],f[i][1])+1,此时如果从 f [ i ] [ 0 ] f[i][0] f[i][0] 转移过来表示被修改子数组从 i i i 位置开始;如果从 f [ i ] [ 1 ] f[i][1] f[i][1] 转移过来表示 n u m s [ i − 1 ] nums[i-1] nums[i1] 也在被修改子数组中。如果 x ! = t a r g e t x != target x!=target f [ i + 1 ] [ 1 ] = m a x ( f [ i ] [ 0 ] , f [ i ] [ 1 ] ) f[i+1][1]=max(f[i][0],f[i][1]) f[i+1][1]=max(f[i][0],f[i][1])
  • 【左 + 中 + 右】可以从【左 + 中】或者【左 + 中 + 右】转移过来,如果 x = = k x == k x==k f [ i + 1 ] [ 1 ] = m a x ( f [ i ] [ 1 ] , f [ i ] [ 2 ] ) + 1 f[i+1][1]=max(f[i][1],f[i][2])+1 f[i+1][1]=max(f[i][1],f[i][2])+1,此时如果从 f [ i ] [ 1 ] f[i][1] f[i][1] 转移过来表示 n u m s [ i − 1 ] nums[i-1] nums[i1] 是被修改子数组的最后一个元素;如果从 f [ i ] [ 2 ] f[i][2] f[i][2] 转移过来表示被修改子数组的最后下标 < i − 1 <i-1 <i1

代码如下:

class Solution {
    public int maxFrequency(int[] nums, int k) {
        Set<Integer> set = new HashSet<>();
        for(int x : nums) set.add(x);
        int n = nums.length;
        int ans = 0;
        for(int tar : set){
            int[][] f = new int[n+1][3];
            for(int i=0; i<n; i++){
                int x = nums[i];
                f[i+1][0] = f[i][0] + (x == k ? 1 : 0);
                f[i+1][1] = Math.max(f[i][0], f[i][1]) + (x == tar ? 1 : 0);
                f[i+1][2] = Math.max(f[i][1], f[i][2]) + (x == k ? 1 : 0);
            }
            ans = Math.max(ans, Math.max(f[n][1], f[n][2]));
        }
        return ans;
    }
}
//化简之后
class Solution {
    public int maxFrequency(int[] nums, int k) {
        Set<Integer> set = new HashSet<>();
        for(int x : nums) set.add(x);
        int n = nums.length;
        int ans = 0;
        for(int tar : set){
            int f0 = 0, f1 = 0, f2 = 0;
            for(int x : nums){
                f2 = Math.max(f1, f2) + (x == k ? 1 : 0);
                f1 = Math.max(f0, f1) + (x == tar ? 1 : 0);
                f0 = f0 + (x == k ? 1 : 0);
            }
            ans = Math.max(ans, Math.max(f1, f2));
        }
        return ans;
    }
}

四、3435. 最短公共超序列的字母出现频率

题目链接
在这里插入图片描述
举一个例子 w o r d s = [ a a , a b , a c , a d , b a , c a ] words=[aa,ab,ac,ad,ba,ca] words=[aa,ab,ac,ad,ba,ca],至少需要几个 a a a 才能满足所有排列,答案是两个,只需要将 a a a 放在两端,我们就可以直接得出 a ∗ a* a a a aa aa ∗ a *a a,(即关于 a a a 的所有排列),对于其它字符也是同理,可以得出一个结论:对于 w o r d s words words 中出现的字符,它要么出现一次,要么出现两次。又因为本题在一个 w o r d s words words 中至多出现16个不同字符,所以可以暴力枚举 w o r d s words words 中不同字符出现的次数来解决这道题。

接下来问题就变成了如何判断这些字符是否有一种排列能满足 w o r d s words words 中的所有字符串是它的子序列:

  • 由上述的推导可知,如果一个字符出现了 2 次,只要放在两端一定可以得到关于它的任意排列,所以这里只需要考虑出现 1 次的字符。
  • 对于只出现 1 次的字符,比如说 abcd 四个字符各出现了一次,如果 w o r d s words words 中有 ab 和 ba,那么不管怎么排列都不可能满足条件,如果把它当成一个有向图,a -> b -> a,也就是说对于只出现 1 次的字符不能出现环,如果出现环,就说明这个字符需要出现 2 次才能满足条件。
  • 判断有向图是否有环可以有两种做法:拓扑排序、三色标记法

代码如下:

//拓扑排序
class Solution {
    public List<List<Integer>> supersequences(String[] words) {
        int all = 0;//统计出现了那些字符
        for(String s : words){
            int x = s.charAt(0) - 'a';
            int y = s.charAt(1) - 'a';
            all |= 1 << x | 1 << y;
        }
        Set<Integer> set = new HashSet<>();
        int minSize = Integer.MAX_VALUE;
        int sub = all;//枚举哪些字符出现2次
        do{
            int size = Integer.bitCount(sub);
            if(size <= minSize && !hasCycle(sub, words)){
                if(size < minSize){
                    minSize = size;
                    set.clear();
                }
                set.add(sub);
            }
            sub = (sub - 1) & all;
        }while(sub != all);
        List<List<Integer>> ans = new ArrayList<>(set.size());
        for(int s : set){
            List<Integer> cnt = new ArrayList<>();
            for(int i=0; i<26; i++){
                cnt.add((all>>i&1)+(s>>i&1));
            }
            ans.add(cnt);
        }
        return ans;
    }
    private boolean hasCycle(int sub, String[] words){
        List<Integer>[] g = new ArrayList[26];
        Arrays.setAll(g, e->new ArrayList<>());
        int[] cnt = new int[26];
        for(String s : words){
            int x = s.charAt(0) - 'a';
            int y = s.charAt(1) - 'a';
            if((sub>>x&1)==0 && (sub>>y&1)==0){
                g[x].add(y);
                cnt[y]++;
            }
        }
        Queue<Integer> que = new LinkedList<>();
        for(int i=0; i<26; i++){
            if(cnt[i] == 0) que.add(i);
        }
        while(!que.isEmpty()){
            int poll = que.poll();
            for(int x : g[poll]){
                if(--cnt[x] == 0)
                    que.add(x);
            }
        }
        for(int x : cnt){
            if(x > 0) return true;
        }
        return false;
    }
}
//三色标记法
class Solution {
    public List<List<Integer>> supersequences(String[] words) {
        int all = 0;
        List<Integer>[] g = new ArrayList[26];
        Arrays.setAll(g, e->new ArrayList<>());
        for(String s : words){
            int x = s.charAt(0) - 'a';
            int y = s.charAt(1) - 'a';
            all |= 1 << x | 1 << y;
            g[x].add(y);
        }
        Set<Integer> set = new HashSet<>();
        int minSize = Integer.MAX_VALUE;
        int sub = all;
        do{
            int size = Integer.bitCount(sub);
            if(size <= minSize && !hasCycle(sub, g)){
                if(size < minSize){
                    minSize = size;
                    set.clear();
                }
                set.add(sub);
            }
            sub = (sub - 1) & all;
        }while(sub != all);
        List<List<Integer>> ans = new ArrayList<>(set.size());
        for(int s : set){
            List<Integer> cnt = new ArrayList<>();
            for(int i=0; i<26; i++){
                cnt.add((all>>i&1)+(s>>i&1));
            }
            ans.add(cnt);
        }
        return ans;
    }
    private boolean hasCycle(int sub, List<Integer>[] g){
        int[] color = new int[26];
        for(int i=0; i<26; i++){
            if(color[i]==0&&(sub>>i&1)==0&&dfs(i, color, g, sub)){
                return true;
            }
        }
        return false;
    }
    private boolean dfs(int x, int[] color, List<Integer>[] g, int sub){
        color[x] = 1;
        for(int y : g[x]){
            if((sub>>y&1)!=0){
                continue;
            }
            if(color[y]==1 || color[y]==0 && dfs(y, color, g, sub)){
                return true;
            }
        }
        color[x] = 2;
        return false;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2293502.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C32.【C++ Cont】静态实现双向链表及STL库的list

目录 1.知识回顾 2.静态实现演示图 3.静态实现代码 1.初始双向链表 2.头插 3.遍历链表 4.查找某个值 4.任意位置之后插入元素 5.任意位置之前插入元素 6.删除任意位置的元素 4.STL库的list 1.知识回顾 96.【C语言】数据结构之双向链表的初始化,尾插,打印和尾删 97.【C…

记录一次-Rancher通过UI-Create Custom- RKE2的BUG

一、下游集群 当你的下游集群使用Mysql外部数据库时&#xff0c;会报错&#xff1a; **他会检查ETCD。 但因为用的是Mysql外部数据库&#xff0c;这个就太奇怪了&#xff0c;而且这个检测不过&#xff0c;集群是咩办法被管理的。 二、如果不选择etcd,就选择控制面。 在rke2-…

51单片机入门_05_LED闪烁(常用的延时方法:软件延时、定时器延时;while循环;unsigned char 可以表示的数字是0~255)

本篇介绍编程实现LED灯闪烁&#xff0c;需要学到一些新的C语言知识。由于单片机执行的速度是非常快的&#xff0c;如果不进行延时的话&#xff0c;人眼是无法识别(停留时间要大于20ms)出LED灯是否在闪烁所以需要学习如何实现软件延时。另外IO口与一个字节位的数据对应关系。 文…

99.20 金融难点通俗解释:中药配方比喻马科维茨资产组合模型(MPT)

目录 0. 承前1. 核心知识点拆解2. 中药搭配比喻方案分析2.1 比喻的合理性 3. 通俗易懂的解释3.1 以中药房为例3.2 配方原理 4. 实际应用举例4.1 基础配方示例4.2 效果说明 5. 注意事项5.1 个性化配置5.2 定期调整 6. 总结7. 代码实现 0. 承前 本文主旨&#xff1a; 本文通过中…

6 [新一代Github投毒针对网络安全人员钓鱼]

0x01 前言 在Github上APT组织“海莲花”发布存在后门的提权BOF&#xff0c;通过该项目针对网络安全从业人员进行钓鱼。不过其实早在几年前就已经有人对Visual Studio项目恶意利用进行过研究&#xff0c;所以投毒的手法也不算是新的技术。但这次国内有大量的安全从业者转发该钓…

MYSQL面试题总结(题目来源JavaGuide)

MYSQL基础架构 问题1&#xff1a;一条 SQL语句在MySQL中的执行过程 1. 解析阶段 (Parsing) 查询分析&#xff1a;当用户提交一个 SQL 语句时&#xff0c;MySQL 首先会对语句进行解析。这个过程会检查语法是否正确&#xff0c;确保 SQL 语句符合 MySQL 的语法规则。如果发现…

redis实际开发应用简单实现

短信登录 首先来看看登录与注册常规实现流程如下&#xff1a; 其中&#xff0c;很多网站都有手机号验证码登录功能 如百度 实现之前咱可以来验证码有啥特点&#xff1a;一定时间内过期、验证码随机、与手机号会唯一匹配 所以可以使用redis的string来实现更容易&#xff0c;k…

Hive on Spark优化

文章目录 第1章集群环境概述1.1 集群配置概述1.2 集群规划概述 第2章 Yarn配置2.1 Yarn配置说明2.2 Yarn配置实操 第3章 Spark配置3.1 Executor配置说明3.1.1 Executor CPU核数配置3.1.2 Executor内存配置3.1.3 Executor个数配置 3.2 Driver配置说明3.3 Spark配置实操 第4章 Hi…

【实践案例】基于大语言模型的海龟汤游戏

文章目录 项目背景提示词构建海龟汤主持人真相判断专家 具体实现流程文心一言大语言模型“海龟汤”插件参考 项目背景 “海龟汤”作为一种聚会类桌游&#xff0c;又称情境推理游戏&#xff0c;是一种猜测情境还原事件真相的智力游戏。其玩法是由出题者提出一个难以理解的事件&…

创建前端项目的方法

目录 一、创建前端项目的方法 1.前提&#xff1a;安装Vue CLI 2.方式一&#xff1a;vue create项目名称 3.方式二&#xff1a;vue ui 二、Vue项目结构 三、修改Vue项目端口号的方法 一、创建前端项目的方法 1.前提&#xff1a;安装Vue CLI npm i vue/cli -g 2.方式一&…

Java 大数据与区块链的融合:数据可信共享与溯源(45)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

STM32单片机学习记录(2.2)

一、STM32 13.1 - PWR简介 1. PWR&#xff08;Power Control&#xff09;电源控制 &#xff08;1&#xff09;PWR负责管理STM32内部的电源供电部分&#xff0c;可以实现可编程电压监测器和低功耗模式的功能&#xff1b; &#xff08;2&#xff09;可编程电压监测器&#xff08;…

ROS应用之SwarmSim在ROS 中的协同路径规划

SwarmSim 在 ROS 中的协同路径规划 前言 在多机器人系统&#xff08;Multi-Robot Systems, MRS&#xff09;中&#xff0c;SwarmSim 是一个常用的模拟工具&#xff0c;可以对多机器人进行仿真以实现复杂任务的协同。除了任务分配逻辑以外&#xff0c;SwarmSim 在协同路径规划方…

蓝桥杯python基础算法(2-1)——排序

目录 一、排序 二、例题 P3225——宝藏排序Ⅰ 三、各种排序比较 四、例题 P3226——宝藏排序Ⅱ 一、排序 &#xff08;一&#xff09;冒泡排序 基本思想&#xff1a;比较相邻的元素&#xff0c;如果顺序错误就把它们交换过来。 &#xff08;二&#xff09;选择排序 基本思想…

linux 进程补充

环境变量 基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 如&#xff1a;我们在编写C/C代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我们的所链接的动态静态库在哪 里&#xff0c;但是照样可以链接成功&#…

C基础寒假练习(8)

一、终端输入10个学生成绩&#xff0c;使用冒泡排序对学生成绩从低到高排序 #include <stdio.h> int main(int argc, const char *argv[]) {int arr[10]; // 定义一个长度为10的整型数组&#xff0c;用于存储学生成绩int len sizeof(arr) / sizeof(arr[0]); // 计算数组…

Python爬虫:1药城店铺爬虫(完整代码)

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(一)

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;贪心算法篇–CSDN博客 文章目录 一.贪心算法1.什么是贪心算法2.贪心算法的特点 二.例题1.柠…

基于Springboot框架的学术期刊遴选服务-项目演示

项目介绍 本课程演示的是一款 基于Javaweb的水果超市管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 3.该项目附…

Java创建对象有几种方式?

大家好&#xff0c;我是锋哥。今天分享关于【Java创建对象有几种方式?】面试题。希望对大家有帮助&#xff1b; Java创建对象有几种方式? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Java 中&#xff0c;创建对象有几种常见的方式&#xff0c;具体如下&…