Leetcode - 周赛394

目录

一,3120. 统计特殊字母的数量 I

二,3121. 统计特殊字母的数量 II

三,3122. 使矩阵满足条件的最少操作次数

四,3123. 最短路径中的边


一,3120. 统计特殊字母的数量 I

本题就是统计有多少个字母的大小写同时出现在字符串word中,分别使用一个数组来统计大写字母和小写字母的出现次数。 

代码如下: 

class Solution {
    public int numberOfSpecialChars(String word) {
        int[] cnt1 = new int[26];//大写
        int[] cnt2 = new int[26];//小写
        for(char ch : word.toCharArray()){
            if(Character.isUpperCase(ch)){
                cnt1[ch-'A']++;
            }else{
                cnt2[ch-'a']++;
            }
        }
        int ans = 0;
        for(int i=0; i<26; i++){
            if(cnt1[i]>0 && cnt2[i]>0)
                ans++;
        }
        return ans;
    }
}

二,3121. 统计特殊字母的数量 II

本题比上一题多了一些条件,不仅要大小写都出现,并且所有的小写字母都要出现在其对应大写字母的前面。所以可以使用两个数组分别存储,一个存储大写字母的第一次出现下标,另一个存储小写字母最后一次出现下标,如果大小写都出现&小写字母的下标<大写字母的下标,那么就+1。

代码如下:

class Solution {
    public int numberOfSpecialChars(String word) {
        int[] idx1 = new int[26];//大写字母第一次出现的下标
        int[] idx2 = new int[26];//小写字母最后一次出现的下标
        Arrays.fill(idx1, -1);
        Arrays.fill(idx2, -1);
        char[] ch = word.toCharArray();
        for(int i=0; i<ch.length; i++){
            if(Character.isLowerCase(ch[i])){
                idx2[ch[i]-'a'] = i;
            }else{
                idx1[ch[i]-'A'] = idx1[ch[i]-'A']==-1?i:idx1[ch[i]-'A'];
            }
        }
        int ans = 0;
        for(int i=0; i<26; i++){
            if(idx1[i]!=-1&&idx2[i]!=-1&&idx1[i]>idx2[i])
                ans++;
        }
        return ans;
    }
}

上述做法更加不容易出错,但是还有更加省时间的做法,可以一次遍历实现,使用一个hash表来统计出现的大小写字母,再使用一个数组 cnt 来统计 26 个字母的状态:

  • 0:该字母没有计入答案
  • 1:该字母已计入答案
  • 2:该字母不可能是答案

遍历该字符串:

  • 如果是大写字母,并且之前出现过小写字母,将cnt[i] = 0 (表示该字母没有被计入ans中),将cnt[i] = 1,ans++
  • 如果是小写字母,并且之前出现过大写字母&& cnt[i] == 1 (表示该字母已经被计入ans中),将cnt[i] = 2 (表示该字母不可能是答案),ans--
  • 如果是大写字母,并且之前没有出现过小写字母,将cnt[i]=2 (表示该字母不可能是答案),防止出现BbB这种情况
class Solution {
    public int numberOfSpecialChars(String word) {
        Set<Character> set = new HashSet<>();//统计大小写
        int[] cnt = new int[26];
        //0:该字母没有计入答案
        //1:该字母已计入答案
        //2:该字母被计入答案后又出现小写字母,又被删除
        int ans = 0;
        for(char ch : word.toCharArray()){
            if(Character.isUpperCase(ch)){
                //小写字母出现后大写字母出现的情况
                if(set.contains(Character.toLowerCase(ch)) && cnt[ch-'A']==0){
                    cnt[ch-'A'] = 1;
                    ans++;
                }
                //出现小写字母未出现,先出现大写字母的情况!!!(容易忽略)
                if(!set.contains(Character.toLowerCase(ch))){
                    cnt[ch-'A'] = 2;
                }
            }else{
                //出现大写字母后,又出现小写字母的情况
                if(set.contains(Character.toUpperCase(ch)) && cnt[ch-'a']==1){
                    cnt[ch-'a'] = 2;
                    ans--;
                }
            }
            set.add(ch);
        }
        return ans;
    }
}

三,3122. 使矩阵满足条件的最少操作次数

没有思路,先考虑暴力求解,也就是枚举每一列选择保留的数字,保证相邻两列保留的数不一样,求保留的最大值,所以 dfs 就需要两个变量,一个存储当前的列数,一个存储上一个保留的数字。

dfs(i,pre) 的定义:前 i 列数可以保留的最大数目。

  • 结束条件:i < 0,返回 0
  • 每次递归要做:使用 j 遍历0~9,res = Math.max( res,dfs(i-1,j)+cnt[ i ][ j ]),cnt[ i ][ j ]表示当前列中有多少个 j 
  • 结果: res
class Solution {
    Map<String, Integer> map = new HashMap<>();
    public int minimumOperations(int[][] grid) {
        int n = grid.length;
        int m = grid[0].length;
        int[][] cnt = new int[m][10];
        for(int i=0; i<n; i++){
            for(int j=0; j<m; j++){
                cnt[j][grid[i][j]]++;
            }
        }
        return n*m - dfs(m-1, cnt, -1);
    }
    int dfs(int i, int[][] cnt, int pre){
        String key = i + "-" + pre;
        if(!map.isEmpty() && map.containsKey(key))
            return map.get(key);
        if(i < 0) return 0;
        int res = 0;
        for(int j=0; j<=9; j++){
            if(j != pre)
                res = Math.max(res, dfs(i-1, cnt, j)+cnt[i][j]);
        }
        map.put(key, res);
        return res;
    }
}

四,3123. 最短路径中的边

本题和上周双周赛一样,考的还是djstra算法,只不过它问的是edges[i]是否在0->n-1节点的最短路径上,这里有两种做法,先讲简单一点的:

使用两次djstra算法,分别算出从0到所有位置的最短路径dis1,以及从n-1到所有位置的最短路径dis2,再遍历edges数组(x=e[0],y=e[1],w=e[2]),判断 dis1[x] + dis2[y] + w == dis1[n-1] 或者 dis1[y] + dis2[x] + w == dis1[n-1],如果相等说明ans[i] = true,否则 ans[i] = false。就是下图两种情况:

代码如下:

class Solution {
    int n;
    public boolean[] findAnswer(int n, int[][] edges) {
        this.n = n;
        List<int[]>[] g = new ArrayList[n];
        Arrays.setAll(g, e->new ArrayList<>());
        for(int i=0; i<edges.length; i++){
            int[] e = edges[i];
            int x = e[0], y = e[1], w = e[2];
            g[x].add(new int[]{y, w});
            g[y].add(new int[]{x, w});
        } 
        int[] dis1 = dis(g, 0);//0->?的最短路径
        int[] dis2 = dis(g, n-1);//n-1 -> ?的最短路径
        
        int mn = dis1[n-1];
        boolean[] ans = new boolean[edges.length];
        for(int i=0; i<edges.length; i++){
            int[] e = edges[i];
            int x = e[0], y = e[1], w = e[2];
            if(dis1[x] + dis2[y] + w == mn || dis1[y]+dis2[x]+w==mn){
                ans[i] = true;
            }else{
                ans[i] = false;
            }
        }
        return ans;
    }
    int[] dis(List<int[]>[] g, int s){
        int[] dis = new int[n];
        Arrays.fill(dis, Integer.MAX_VALUE/2);
        dis[s] = 0;
        PriorityQueue<int[]> que = new PriorityQueue<>((x,y)->x[0]-y[0]);
        que.offer(new int[]{0, s});
        while(!que.isEmpty()){
            int[] t = que.poll();
            int dx = t[0];
            int x = t[1];
            if(dx > dis[x]){
                continue;
            }
            for(int[] y : g[x]){
                int idx = y[0];
                int newDis = dx + y[1];
                if(dis[idx]==Integer.MAX_VALUE/2 || newDis < dis[idx]){
                    dis[idx] = newDis;
                    que.offer(new int[]{newDis,idx});
                }
            }
        }
        return dis;
    }
}

另一种解法和上述解法的思路是相同的,但是时间复杂度更低,只使用一次djstra算法,算出从0到所有位置的最短路径dis,然后从n-1出发,倒着dfs,如果dis[y] + w == dis[x],就说明当前x-y这段路径在最短路径上。

代码如下:

class Solution {
    public boolean[] findAnswer(int n, int[][] edges) {
        List<int[]>[] g = new ArrayList[n];
        Arrays.setAll(g, e->new ArrayList<>());
        for(int i=0; i<edges.length; i++){
            int[] e = edges[i];
            int x = e[0], y = e[1], w = e[2];
            g[x].add(new int[]{y, w, i});
            g[y].add(new int[]{x, w, i});
        }
        PriorityQueue<int[]> que = new PriorityQueue<>((x,y)->x[0]-y[0]);
        que.offer(new int[]{0, 0});
        int[] dis = new int[n];
        Arrays.fill(dis, Integer.MAX_VALUE/2);
        dis[0] = 0;
        while(!que.isEmpty()){
            int[] t = que.poll();
            int dx = t[0];
            int x = t[1];
            if(dx > dis[x]) continue;
            for(int[] y : g[x]){
                int idx = y[0];
                int newDis = dx + y[1];
                if(dis[idx]==Integer.MAX_VALUE/2 || newDis < dis[idx]){
                    dis[idx] = newDis;
                    que.offer(new int[]{newDis, idx});
                }
            }
        }
        boolean[] ans = new boolean[edges.length];
        if(dis[n-1] == Integer.MAX_VALUE/2) return ans;
        boolean[] vis = new boolean[n];
        dfs(n-1, dis, ans, vis, g);
        return ans;
    }
    void dfs(int x, int[] dis, boolean[] ans, boolean[] vis, List<int[]>[] g){
        vis[x] = true;
        for(int[] t : g[x]){
            int y = t[0], w = t[1], i = t[2];
            if(dis[y] + w != dis[x])
                continue;
            ans[i] = true;
            if(!vis[y]){
                dfs(y, dis, ans, vis, g);
            }
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AIGC学习步骤

目录 AIGC学习步骤 步骤一&#xff1a;理解基本概念 步骤二&#xff1a;学习资源 步骤三&#xff1a;深入研究 步骤四&#xff1a;联系专家 步骤五&#xff1a;实践应用 步骤六&#xff1a;持续学习 AIGC学习步骤 我们先来说说什么是AIGC&#xff1f; 生成式人工智能—…

第二篇:Python环境搭建:从初学者到专家

Python环境搭建&#xff1a;从初学者到专家 在编程的世界里&#xff0c;准备好一个高效而舒适的开发环境是走向成功的第一步。在这篇博客文章中&#xff0c;我们将一起探索如何为Python编程搭建一个理想的环境。无论你是完全的新手还是希望提升现有的技能&#xff0c;本文都会…

IDEA快速入门

目录 1. 概述 2. 安装 3. 激活 4. 关闭自动更新 5. 创建Java项目 5.1 配置JRE 5.2 创建项目 6. 配置设置 6.1 主题 6.2 设置字体默认大小 6.3 鼠标滚轮改变字体大小 6.4 设置自动导入 6.5 项目选择 7. lombok插件 7.1 安装插件 7.2 启用注解 8. 安装包及插件…

SecuPress Pro 专业级WordPress网站安全防护插件优化版

下载地址&#xff1a;SecuPress Pro 专业版.zip SecuPress Pro&#xff1a;专业的WordPress安全解决方案 如果您没有时间进行每周扫描&#xff0c;SecuPress Pro将是您的理想选择。SecuPress Pro提供了所有SecuPress Free的功能&#xff0c;同时还增加了一些高级选项&#xff…

优维全新力作:统一采控平台

在本月&#xff0c;优维新一代核心系统「EasyOps」7.0大版本重磅上线&#xff0c;为广大用户带来了“更核心、更智能、更开放、更客制”的产品能力。&#xff08;点击回看&#xff1a;重磅&#xff01;优维科技发布EasyOps7.0大版本&#xff09;在本次版本能力分享上&#xff0…

VBA技术资料MF145:清空回收站

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

各种CSS导航代码集合!CV即可!水平导航,垂直导航,jd粘性导航…

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

mysql的多表查询和子查询

多表查询&#xff1a;查询数据时&#xff0c;需要使用多张表来查询 多表查询分类&#xff1a; 1.内连接查询 2.外连接查询 3.子查询 笛卡尔积&#xff1a; create table class (id int primary key auto_increment,name varchar(10) ); create table student (id int primar…

【TCP:可靠数据传输,快速重传,流量控制,TCP流量控制】

文章目录 可靠数据传输TCP&#xff1a;可靠数据传输TCP发送方事件快速重传流量控制TCP流量控制 可靠数据传输 TCP&#xff1a;可靠数据传输 TCP在IP不可靠服务的基础上建立了rdt 管道化的报文段 GBN or SR 累计确认&#xff08;像GBN&#xff09;单个重传定时器&#xff08;像…

搞懂特殊的引用类型接口、枚举、注解、记录、包装类!

面向对象系列——特殊的引用类型&#xff08;与class并列地位&#xff09; 文章目录 面向对象系列——特殊的引用类型&#xff08;与class并列地位&#xff09;特殊的&#xff1a;接口、枚举、注解、记录&#xff0c;包装类一、interface接口(不是类)—提供一种规范(具有多态性…

ionic 中对Input输入框、searchbar进行solr检索

一、概述 Ionic 是一个用于开发跨平台应用程序的开源工具&#xff0c;可以使用 Angular、React 或 Vue 等前端框架。要在 Ionic 应用程序中实现实时与 Solr 通信&#xff0c;可以使用 HTTP 客户端&#xff08;如 Angular 的 HttpClient 或 Ionic 的 Native HTTP&#xff09;…

MySQL—MySQL的存储引擎之InnoDB

MySQL—MySQL的存储引擎之InnoDB 存储引擎及种类 存储引擎说明MyISAM高速引擎&#xff0c;拥有较高的插入&#xff0c;查询速度&#xff0c;但不支持事务InnoDB5.5版本后MySQL的默认数据库存储引擎&#xff0c;支持事务和行级锁&#xff0c;比MyISAM处理速度稍慢ISAMMyISAM的…

一分钟教你下载小程序视频到手机#下载高手

本文就教你们如何下载小程序的视频到手机 首先将小程序视频下载到电脑上&#xff0c;然后再传送到手机上,这样就实现了下载小程序到手机上 可是怎么将小程序下载到电脑上呢&#xff1f;这里要借用一个工具&#xff1a;下载高手 下载高手工具我已经打包好了&#xff0c;有需要…

【算法题解】

文章目录 day4_26最长回文子串思路&#xff1a;代码&#xff1a; **DP30** **买卖股票的最好时机(一)**思路&#xff1a;贪心代码&#xff1a; 过河卒思路&#xff1a;动态规划---路径类代码&#xff1a; day4_26 https://www.nowcoder.com/questionTerminal/12e081cd10ee4794…

生命周期评估(LCA)Simapro软件应用与碳足迹分析

各企事业单位&#xff1a; SimaPro以系统和透明的方式轻松建模和分析复杂的生命周期&#xff0c;通过确定供应链中每个环节的热点&#xff0c;从原材料的提取到制造&#xff0c;分销&#xff0c;使用和处置&#xff0c;衡量所有生命周期阶段的产品和服务对环境的影响。SimaPro是…

又重新搭了个个人博客

哈喽大家好&#xff0c;我是咸鱼。 前段时间看到一个学弟写了篇用 Hexo 搭建博客的教程&#xff0c;心中沉寂已久的激情重新被点燃起来。&#xff08;以前搞过一个个人网站&#xff0c;但是因为种种原因最后不了了之&#xff09; 于是花了一天时间参考教程搭了个博客网站&…

广工电工与电子技术实验报告-8路彩灯循环控制电路

实验代码 module LED_water (clk,led); input clk; output [7:0] led; reg [7:0] led; integer p; reg clk_1Hz; reg [7:0] current_state, next_state; always (posedge clk) begin if(p25000000-1)begin …

JVM(Jvm如何管理空间?对象如何存储、管理?)

Jvm如何管理空间&#xff08;Java运行时数据区域与分配空间的方式&#xff09; ⭐运行时数据区域 程序计数器 程序计数器&#xff08;PC&#xff09;&#xff0c;是一块较小的内存空。它可以看作是当前线程所执行的字节码的行号指示器。Java虚拟机的多线程是通过时间片轮转调…

Flutter 从 Assets 中读取 JSON 文件:指南 [2024]

在本教程中&#xff0c;我们将探讨如何从 Flutter 项目中的 asset 中读取 JSON 文件。您将找到详细的解释、实际示例和最佳实践&#xff0c;使您的 JSON 文件处理顺利高效。那么&#xff0c;让我们深入了解 Flutter 和 JSON 的世界吧&#xff01; 从 asset 中读取 JSON 文件 …

RTK负载(4K可见光+高分热成像+超广角+激光测距)四光AI智能识别跟踪吊舱技术详解

无人机光电吊舱的RTK负载&#xff08;4K可见光高分热成像超广角激光测距&#xff09;AI智能识别跟踪吊舱技术是一种高度集成和先进的无人机观测系统。系统结合了无人机的飞行能力和光电吊舱的多功能传感器&#xff0c;通过集成RTK&#xff08;实时动态差分定位&#xff09;技术…