【LeetCode周赛】2022上半年题目精选集——思维题

news2024/11/24 18:35:26

文章目录

    • 2211. 统计道路上的碰撞次数(栈 || 脑筋急转弯)
      • 解法1:自己想的——使用栈
      • 解法2——思维:去掉左右两边往左右开的车
        • 代码写法1——找左右端点
        • 代码写法2——正则表达式去除+流处理api
          • 补充:replaceAll() 和 正则表达式
          • 补充:(int) s.chars().filter(c -> c == 'S').count(); 解释
    • 2227. 加密解密字符串 (逆向思维)
      • 思路
      • 代码1
      • 代码2
    • 2242. 节点序列的最大得分⭐⭐⭐⭐⭐ (有技巧的枚举)
      • 思路——有技巧的枚举(枚举中间的边)
      • 代码
    • 2306. 公司命名⭐⭐⭐⭐⭐(分类讨论)
    • 2317. 操作后的最大异或和(位运算)
      • 思路
      • 代码
  • 相关链接

2211. 统计道路上的碰撞次数(栈 || 脑筋急转弯)

2211. 统计道路上的碰撞次数

难度:1581
在这里插入图片描述
提示:

1 <= directions.length <= 10^5
directions[i] 的值为 'L'、'R' 或 'S'

解法1:自己想的——使用栈

受 2126. 摧毁小行星 这道题的启发,使用栈来处理这个问题。

当枚举到 ‘R’ 和 ‘S’ 时,先放入栈中不做处理;
当枚举到 ‘L’ 时,如果此时栈中不为空,那么它会发生碰撞并停下来,因此 ans ++ ,并放入栈中一个 ‘S’;

枚举完毕后,再来处理栈中的 ‘R’,只要 ‘R’ 的上方有 ‘S’ 存在,就会贡献一个 ans ++。

class Solution {
    public int countCollisions(String directions) {
        Deque<Character> stk = new ArrayDeque();
        int ans = 0;
        for (char ch: directions.toCharArray()) {
            if (ch == 'L') {
                if (!stk.isEmpty()) {
                    stk.push('S');
                    ++ans;
                }
            } else stk.push(ch);
        }
        boolean f = false;
        while (!stk.isEmpty()) {
            char ch = stk.pop();
            if (ch == 'R' && f) ++ans;
            if (ch != 'R') f = true;
        }
        return ans;
    }
}

时间复杂度是 O ( n ) O(n) O(n)

解法2——思维:去掉左右两边往左右开的车

去掉往左右两边开的车之后,剩下非停止的车必然会碰撞。

代码写法1——找左右端点

分别找到两边去掉之后的端点,枚举端点范围内的车辆,每个 L 和 R 都会贡献一个答案 ans++。

class Solution {
    public int countCollisions(String directions) {
        int n = directions.length(), l = 0, r = n - 1, ans = 0;
        while (l < n && directions.charAt(l) == 'L') ++l;
        while (r >= 0 && directions.charAt(r) == 'R') --r;
        for (int i = l; i <= r; ++i) {
            if (directions.charAt(i) != 'S') ++ans;
        }
        return ans;
    }
}

代码写法2——正则表达式去除+流处理api

class Solution {
    public int countCollisions(String s) {
        // 前缀向左的车不会发生碰撞
        s = s.replaceAll("^L+", ""); 
        // 后缀向右的车不会发生碰撞
        s = new StringBuilder(s).reverse().toString().replaceAll("^R+", ""); 
        // 剩下非停止的车必然会碰撞
        return s.length() - (int) s.chars().filter(c -> c == 'S').count(); 
    }
}
补充:replaceAll() 和 正则表达式

Java 中的 String 类的 replaceAll() 方法是用来使用给定的 replacement 字符串替换此字符串匹配给定的正则表达式的每个子字符串。
它的语法是:

public String replaceAll(String regex, String replacement)

其中,regex 是要替换的正则表达式,replacement 是用来替换每个匹配项的字符串。

关于正则表达式
在这里插入图片描述
更多关于正则表达式可见:正则表达式 - 廖雪峰的官方网站

本题中用到的 ^L+ 表示 匹配 1 个或多个位于字符串开头的 L。

补充:(int) s.chars().filter(c -> c == ‘S’).count(); 解释

对应代码中的这一句:

return s.length() - (int) s.chars().filter(c -> c == 'S').count(); 

由于解释太长,已经放在了:【Java语法小记】求字符串中某个字符的数量——IntStream流的使用 中。

2227. 加密解密字符串 (逆向思维)

2227. 加密解密字符串

难度:1944

在这里插入图片描述
提示:

1 <= keys.length == values.length <= 26
values[i].length == 2
1 <= dictionary.length <= 100
1 <= dictionary[i].length <= 100
所有 keys[i] 和 dictionary[i] 互不相同
1 <= word1.length <= 2000
1 <= word2.length <= 200
所有 word1[i] 都出现在 keys 中
word2.length 是偶数
keys、values[i]、dictionary[i]、word1 和 word2 只含小写英文字母
至多调用 encrypt 和 decrypt 总计 200 次

思路

读懂题就已经很难了!

它初始给的代码框架长这样:

class Encrypter {

    public Encrypter(char[] keys, String[] values, String[] dictionary) {

    }
    
    public String encrypt(String word1) {

    }
    
    public int decrypt(String word2) {

    }
}

我们要填写构造方法加密方法计算解密后的数量方法

思路:

  • 构造方法用来定义一些会被使用到的数据结构。
  • 加密方法按照题目要求进行模拟即可。
  • 为了计算解密后出现在 dictionary 中字符串的数量,我们可以提前预处理出所有 dictionary 加密后的字符串并计数保存,这样在解密方法中直接查表就好了。

代码1

class Encrypter {
    char[] keys;
    String[] values, dictionary;
    Map<Character, Integer> m = new HashMap();
    Map<String, Integer> ans = new HashMap();

    public Encrypter(char[] keys, String[] values, String[] dictionary) {
        this.keys = keys;
        this.values = values;
        this.dictionary = dictionary;
        // 存储key中字符和对应的下标
        for (int i = 0; i < keys.length; ++i) m.put(keys[i], i);
        // 提前计算加密结果
        for (String d: dictionary) {
            String dd = encrypt(d);
            // 这里使用 dd + d.length() 作为键是为了确保我们找的加密前字符串的长度是解密前字符串长度的1/2,直接使用dd的话会被最后一个样例卡住
            // 即a对应bb,bbbb应该被解密成aa,但abb这个字符串加密之后也会成为bbbb影响答案计算
            ans.merge(dd + d.length(), 1, Integer::sum);
        }
    }
    
    public String encrypt(String word1) {
        StringBuilder ans = new StringBuilder();
        for (char ch: word1.toCharArray()) {
            if (m.containsKey(ch)) ans.append(values[m.get(ch)]);
            else ans.append(ch);
        }
        return ans.toString();
    }
    
    public int decrypt(String word2) {
    	// 直接查表即可
        return ans.getOrDefault(word2 + (word2.length() / 2), 0);
    }
}

代码2

代码2的加密过程中,如果查询到了不在 key 中的字符,就会直接 return “” ,这样就使得加密过程产出的所有字符串都是全加密的(即字符串中的每个字符都映射成了新的字符串)。

这样也就避免了代码 1 注释中所说的问题:(

// 这里使用 dd + d.length() 作为键是为了确保我们找的加密前字符串的长度是解密前字符串长度的1/2,直接使用dd的话会被最后一个样例卡住
// 即a对应bb,bbbb应该被解密成aa,但abb这个字符串加密之后也会成为bbbb影响答案计算

而题目中的提示说明了 所有 word1[i] 都出现在 keys 中 ,所以不用担心这种写法对于加密结果的影响。

class Encrypter {
    Map<String, Integer> cnt = new HashMap();
    String[] map = new String[26];

    public Encrypter(char[] keys, String[] values, String[] dictionary) {
        // 记录字符c对应keys中下标i所在的values[i]
        for (int i = 0; i < keys.length; ++i) {
            map[keys[i] - 'a'] = values[i];
        }
        // 预处理dictionary加密
        for (String s: dictionary) {
            String e = encrypt(s);
            cnt.merge(e, 1, Integer::sum);
        }
    }
    
    public String encrypt(String word1) {
        StringBuilder res = new StringBuilder();
        for (char ch: word1.toCharArray()) {
            String s = map[ch - 'a'];
            if (s == null) return "";
            res.append(s);
        }
        return res.toString();
    }
    
    public int decrypt(String word2) {
        return cnt.getOrDefault(word2, 0);
    }
}

2242. 节点序列的最大得分⭐⭐⭐⭐⭐ (有技巧的枚举)

2242. 节点序列的最大得分

难度:2304

在这里插入图片描述

思路——有技巧的枚举(枚举中间的边)

在这里插入图片描述

Q:为什么枚举中间的边效率最好?
A:因为枚举一条边的同时就会确定两个点,这时只需要再对这两个点找到相邻最大的点就可以了。

代码

class Solution {
    public int maximumScore(int[] scores, int[][] edges) {
        int n = scores.length;
        List<int[]>[] g = new ArrayList[n];
        Arrays.setAll(g, e -> new ArrayList());
        for (int[] edge: edges) {
            int x = edge[0], y = edge[1];
            g[x].add(new int[]{scores[y], y});
            g[y].add(new int[]{scores[x], x});
        }
        for (int i = 0; i < n; ++i) {
            // 如果和i相连的点的数量>3,就可以删掉只剩3个最大的
            // 这样删可以确保和它组成一个序列的另外3个值都不会被删掉
            // 即对于序列a-x-y-b,枚举到x的时候要保证a,y,b都不会被删掉
            // 删去其它的边是为了后面遍历的时候快一些
            if (g[i].size() > 3) {
                g[i].sort((a, b) -> (b[0] - a[0]));     // 按照score从大到小排序
                g[i] = new ArrayList<>(g[i].subList(0, 3));
            }
        }

        int ans = -1;
        // 枚举每个边作为中间的边
        for (int[] edge: edges) {
            int x = edge[0], y = edge[1];
            for (int[] p: g[x]) {
                int a = p[1];       // x旁边的节点号a
                for (int[] q: g[y]) {
                    int b = q[1];   // y旁边的节点号b
                    if (a != y && b != x && a != b) {
                        ans = Math.max(ans, p[0] + q[0] + scores[x] + scores[y]);
                    }
                }
            }
        }
        return ans;
    }   
}

2306. 公司命名⭐⭐⭐⭐⭐(分类讨论)

2306. 公司命名

难度:2305

在这里插入图片描述
提示:

2 <= ideas.length <= 5 * 10^4
1 <= ideas[i].length <= 10
ideas[i] 由小写英文字母组成
ideas 中的所有字符串 互不相同

从数据范围来看 O ( n 2 ) O(n^2) O(n2) 的算法是不行的。

因此我们来考虑:
在这里插入图片描述
核心思想就是将每个字符串的首字符和其余部分分开,分组统计,分别计算出 有i无j 和 有j无i 的组的数量,最后计算答案。

class Solution {
    public long distinctNames(String[] ideas) {
        // 按照ideas[1:]分组,记录这个组的首字母有哪些(通过mask存储)
        Map<String, Integer> group = new HashMap();
        for (String idea: ideas) {
            String t = idea.substring(1);
            group.put(t, group.getOrDefault(t, 0) | 1 << (idea.charAt(0) - 'a'));
        }

        long ans = 0;
        int[][] cnt = new int[26][26];              // cnt[i][j]表示没i有j的组的个数
        for (int mask: group.values()) {
            // 计算cnt[i][j]
            for (int i = 0; i < 26; ++i) {
                for (int j = i + 1; j < 26; ++j) {
                    if ((mask >> i & 1) == 0 && (mask >> j & 1) == 1) ++cnt[i][j];
                    else if ((mask >> i & 1) == 1 && (mask >> j & 1) == 0) ++cnt[j][i];
                }
            }
        }
        // 所有成对的 cnt[i][j]和cnt[j][i] 可以贡献方案数
        for (int i = 0; i < 26; ++i) {
            for (int j = i + 1; j < 26; ++j) {
                ans += cnt[i][j] * cnt[j][i];
            }
        }
        return ans * 2;
    }
}

2317. 操作后的最大异或和(位运算)

2317. 操作后的最大异或和

难度:1678
在这里插入图片描述

思路

先分析 nums[i] AND (nums[i] XOR x) 的结果:
由于是 AND ,所以 结果中 1 的数量一定小于 nums[i] 中 1 的数量;
由于 x 是任意取的,所以 nums[i] XOR x 可以获得任意数字,
因此 nums[i] AND (nums[i] XOR x) 的最终结果是可以删去 nums[i] 二进制表示中任意数量的 1

我们知道异或的性质是:相同得0,不同得1
要想获得最大值,那就将尽可能多的位置上变成 1。
可以要想变成 1 ,就必须是 1 和 0 之间得异或,即这个位置上本来就有 1 ,我们就可以将其保留下来。

=》有 1 就保留 1 ,这是 或运算 的性质。

因此最终结果就是所有数字 或 起来的结果。

代码

class Solution {
    public int maximumXOR(int[] nums) {
        int ans = 0;
        for (int num: nums) ans |= num;
        return ans;
    }
}

相关链接

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

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

相关文章

VS2022 And QtCreator10 调试 Qt 源码教程

文章目录 背景IDE 调试 Qt 源码Visual Studio 2022Qt Creator 10.0.1 排查思路姊妹篇系列 简 述&#xff1a; 记录使用 Visual Studo 2022 和 QtCreator10 调试 Qt 5.15 源码和 加载 .pdb 的方法。 本文初发于 “偕臧的小站”&#xff0c;同步转载于此。 背景 源码&#xff1a;…

8、动手学深度学习——现代卷积神经网络:AlexNet

1、学习表征 在2012年前&#xff0c;图像特征都是机械地计算出来的。事实上&#xff0c;设计一套新的特征函数、改进结果&#xff0c;并撰写论文是盛极一时的潮流 另一组研究人员&#xff0c;包括Yann LeCun、Geoff Hinton、Yoshua Bengio、Andrew Ng、Shun ichi Amari和Juer…

Java阶段四Day11

Java阶段四Day11 文章目录 Java阶段四Day11Spring AOPElasticsearch1. 关于各种数据库的使用2. 关系型数据库中的索引3. 安装与启动elasticsearch4. 访问elasticsearch5. 使用elasticsearch分词6. elasticsearch文档的相关概念7. 使用elasticsearch添加数据7.1. 添加文档7.2. 查…

Spring Boot 中的分布式追踪及使用

Spring Boot 中的分布式追踪及使用 随着互联网应用程序的复杂性不断增加&#xff0c;分布式系统已经成为了许多企业级应用程序的标配。在分布式系统中&#xff0c;由于服务之间的调用关系错综复杂&#xff0c;很难追踪到一个请求在整个系统中的执行路径和时间&#xff0c;这就…

Python如何提高工作效率,轻松实现读取分数,计算出最高/低分

前言 Python如何读取分数&#xff0c;计算最高/低分 与平均分&#xff1f; 今天这篇文章就来带你学习学习如何实现这个功能~ 环境使用: Python 3.8 解释器 Pycharm 编辑器 涉及知识点 文件读写基础语法字符串处理循环遍历 代码展示 模块 import platform定义获取最高分、最…

AI 语音 - 人声歌曲合成

前情提要 2023-07-02 周日 杭州 阴晴不定 小记: 天生五音不全&#xff0c;唱歌永远找不到调&#xff0c;使用下 AI 通过音色合成下吧&#xff0c;目前才训练 15000 步左右&#xff0c;我准备的数据集其实满打满算也只有 40min 左右的数据集&#xff0c;为了数据预处理有删减了…

基于openvino+yolov5的模型量化记录(PTQ模式)

本文主要是记录学习openvino_notebootk 302-pytorch-quantization-aware-training文档的一些收获&#xff0c;对于yolov5在cpu部署感兴趣的可以参考下。 此文档的目的是为了了解openvino如何降低模型部署的推理时间&#xff0c;同时尽可能保证精度。 此文档一共提供了两种PT…

【Flutter】Flutter 使用 Stream Transform 包处理流操作

文章目录 一、 前言二、 Stream Transform 包简介三、 安装和版本信息四、 Stream Transform 的基本使用1. 扩展方法2. 异步映射 五、 示例&#xff1a;使用 Stream Transform 实现实时搜索功能六、 总结 一、 前言 欢迎来到我的博客&#xff01;我是小雨青年&#xff0c;这是…

基于docker的ubuntu云服务器jupyter深度学习环境配置指南

step1 安装docker 文档中的命令如下&#xff1a; sudo apt-get update sudo apt-get install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings…

驱动 控制开发版3盏灯、蜂鸣器、风扇、马达

head.h #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }gpio_t; //查看开发扩展板原理图可知 //蜂鸣器 PB6 //风扇 PE9 //马达 PF6 //LED1 PE…

商用车线控底盘需求文档

一、 概述 商用车线控底盘主要用于接收智能驾驶域控制器&#xff08;控制器ADU&#xff09;的请求指令&#xff0c;完成ADU 对驱动、制动、档位转向、驻车声光等部分的指令控制&#xff0c;从而实现智能驾驶功。 即 ADU 可通过 CAN 通讯的方式以特定周期和指令控制 一台车的线控…

驱动开发作业2 —— ioctl

通过ioctl函数选择不同硬件的控制&#xff0c;如实现对LED、蜂鸣器、马达、风扇的控制 1.将GPIO的相关寄存器封装成结构体 --------> gpio.h 2.LED相关驱动文件 --------> led.c 3.蜂鸣器相关驱动文件 --------> beep.c 4.风扇相关驱动文件 --------> fan.c 5.马…

Ubuntu/Debian等Linux系统安装微信客户端

【写在前面】 由于本人的工作环境基本是在ubuntu下&#xff0c;而ubuntu使用网页版微信常常会出现无法登陆的现象&#xff0c;为了能够在linux系统用上微信&#xff0c;于是在网上找了找办法&#xff0c;没想到还真有大神做了&#xff0c;特此分享出来。 【安装步骤】 其实只…

UNIX网络编程卷一 学习笔记 第二十二章 高级UDP套接字编程

TCP是一个字节流协议&#xff0c;又使用滑动窗口&#xff0c;因此没有记录边界或发送者数据发送能力超过接收者接受能力之类的事情&#xff0c;但对于UDP&#xff0c;每个输入操作对应一个UDP数据报&#xff08;一个记录&#xff09;&#xff0c;因此当收取的数据报大于引用的输…

软件测试--Fiddler的使用(持续更新)

1.工具界面介绍 2.抓取请求 打开Fiddler,随便访问一些网址,左边便会抓取到很多请求 3.删除请求(Remove all或者输入命令) 4.过滤请求 ps: 5.打开抓HTTPS设置 6.界面熟悉 7.抓包图标说明

MPC vs Multi-sig——误解及重点关注

1. 引言 资金托管的2大主流方案为&#xff1a; MPC&#xff1a;MPC钱包——对应EOA账号。用于高信任企业场景。Multi-sig&#xff1a;多签钱包——对应智能合约钱包。用于个人场景&#xff0c;可强化安全性并易于恢复。 不过V神认为&#xff0c;基于MPC的EOA账号存在根本性缺…

不变的誓言 字符串常量

## 不变的誓言 字符串常量字符串常量&#xff0c;这节课的主题、 水帘洞一直都没有变1.什么是字符串呢&#xff1f; 就是一个一个字符连起来就是字符串&#xff0c;qq聊天 都是字符串。 字符串常量&#xff0c;“”1.什么是字符串呢&#xff1f; 就是一个一个字符连起来就是字…

sqlserver收缩数据库

1.收缩数据库 首先收缩的前提是需要有可用空间如下图&#xff0c;没有可用空间无法收缩数据库 2.减小数据库大小 通过链接: 查询数据库中各表的大小 如果查询的比较大而且无用的数据可以直接把表结构给拿出来&#xff0c;然后删除该表空间就直接释放出来了 3.收缩文件 我…

SpringBoot项目打包部署后页面无法访问问题定位处理记录

问题描述 项目在idea中可以正常访问&#xff0c;但是达成jar包后访问时候访问异常&#xff0c;并报错&#xff0c;部分异常栈如下: org.thymeleaf.exceptions.TemplateInputException: Error resolving template [/views/login], template might not exist or might not be a…

插入排序(直接插入排序 折半插入排序)

直接插入排序 void InsertSort(ElemType A[],int n) {int i,j;for(i2;i<n;i)if(A[i]<A[i-1]){A[0]A[i];for(ji-1;A[0]<A[j];--j)A[j1]A[j];A[j1]A[0];} }折半插入排序 void BinInsertSort(int A[],int n) {int i,j,low,high,mid;for(i2;i<n;i){A[0]A[i];low1;high…