LeetCode 744, 49, 207

目录

  • 744. 寻找比目标字母大的最小字母
    • 题目链接
    • 标签
    • 思路
    • 代码
  • 49. 字母异位词分组
    • 题目链接
    • 标签
    • 思路
    • 代码
  • 207. 课程表
    • 题目链接
    • 标签
    • 思路
    • 代码

744. 寻找比目标字母大的最小字母

题目链接

744. 寻找比目标字母大的最小字母

标签

数组 二分查找

思路

本题比 基础二分查找 难的一点是 需要处理数组中的重复值,另外需要提前判断目标字母target是否比字符数组letters中最大的字母letters[letters.length - 1]还要大,如果是,则按照题目要求直接返回letters的第一个字符;否则才进行二分查找。

如何处理重复值?可以 在找到与target相同的字符时,不急于返回这个字符,而是继续缩小查询区间

而缩小查询区间的策略与题目的要求有关,如果要找 小于target的字符,则下一轮在 左子区间 查询,最后的右指针right就指向小于target的元素;如果要找 大于target的字符,则下一轮在 右子区间 查询,最后的左指针left就指向大于target的元素

例如对于在letters = ['a', 'a', 'b', 'b', 'c', 'c']中查找大于target = 'b'的字符,有如下的二分查找流程:

开始left = 0, right = 5, mid = 2,发现target == letters[mid],于是下一轮查询右子区间;
此时left = 3, right = 5, mid = 4,发现target < letters[mid],于是下一轮查询左子区间;
此时left = 3, right = 3, mid = 3,发现target == letters[mid],于是下一轮查询右子区间;
此时left = 4, right = 3,有left > right,退出查找。

最后left4,而letters[left]'c',这正是要求查找的字符。

代码

class Solution {
    public char nextGreatestLetter(char[] letters, char target) {
        int left = 0, right = letters.length - 1;
        if (target >= letters[right]) { // 如果letters中没有比target大的字符
            return letters[0]; // 则返回letters的第一个字符
        }
        while (left <= right) {
            int mid = left + (right - left >> 1);
            if (target < letters[mid]) { // 若target小于mid指向的元素
                right = mid - 1; // 则下一轮查找左子区间
            } else if (target > letters[mid]) { // 若target大于mid指向的元素
                left = mid + 1; // 则下一轮查找右子区间
            } else { // 由于不确定mid是否为 最后一个等于target的字符
                left = mid + 1; // 所以下一轮查找右子区间,而不是急于返回
            }
        }
        // 循环结束后left指向letters中第一个大于target的元素
        return letters[left];
    }
}

49. 字母异位词分组

题目链接

49. 字母异位词分组

标签

数组 哈希表 字符串 排序

思路

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。所以字母异位词不关心字符的顺序,只关心 字符的出现次数

所以可以 将字符串中的字符出现次数作为字符串的键,将这个字符串存储到 这个键对应的字符串链表中,即有如此结构Map<Cnt, List<String>>。这里的Cnt是自己实现的数据类型,它内部存储着字符的出现次数,并重写了equals & hashCode方法,可以作为HashMap的键。

将字符串根据不同的字符出现此时分配完之后,将Mapvalues()作为构建ArrayList的参数,构建一个List<List<String>>,并将其返回。

代码

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<Cnt, List<String>> map = new HashMap<>();
        for (String str : strs) {
            Cnt cnt = new Cnt(str); // 获取这个字符串的字符出现次数
            // 获取cnt对应的字符串链表,如果没有,则创建一个新链表
            List<String> list = map.computeIfAbsent(cnt, k -> new ArrayList<>());
            list.add(str); // 将这个字符串放入cnt对应的字符串链表中
        }
        // 由map的多个 字符串链表List<String> 构建一个 List<List<String>> 并返回
        return new ArrayList<>(map.values());
    }
    private static class Cnt { // 统计字符串的字符出现次数
        private int[] key = new int[26];
        public Cnt(String str) { // 计算字符串str的字符出现次数 并保存
            for (int i = 0; i < str.length(); i++) {
                key[str.charAt(i) - 'a']++;
            }
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Cnt cnt = (Cnt) o;
            return Arrays.equals(key, cnt.key);
        }
        @Override
        public int hashCode() { // 以统计数组key作为本对象生成的hashCode
            return Arrays.hashCode(key);
        }
    }
}

207. 课程表

题目链接

207. 课程表

标签

深度优先搜索 广度优先搜索 图 拓扑排序

思路

要做本题需要对 图论 有一定的了解:

  • 节点:图中的一个点。
  • 边:连通一个点到另一个点。对于 有向图 来说,指向别的节点的节点称为 始点,被指向的节点称为 终点
  • 入度:对于一个节点来说,它的入度就是它作为 终点 的次数。

有向图

例如对于上面这个有向图,有以下的结论:

节点1的入度为0
节点2的入度为1
节点3的入度为1
节点4的入度为1
节点5的入度为1
节点6的入度为1
节点7的入度为1
节点8的入度为1
节点9的入度为1
节点10的入度为4
节点11的入度为1

本题很像 图的拓扑排序入度越小,越靠前。在排序之前,先将所有入度为0的节点加入 队列,然后将队列中的节点移出队列,并把节点所指向的节点的入度减一,当某个节点的入度被减到0时,将它加入队列,重复这样的操作,直到队列为空。如果需要返回拓扑排序的结果,则在将节点移出队列时将其加入到结果链表中即可。

回到本题上,要使用拓扑排序得先构建图,并获取图中每个节点的入度,然后才能进行拓扑排序,在拓扑排序的时候记录移出队列的节点数,如果最终这个数字与图中的节点数不一致,则返回false,否则返回true

图实际上就是一堆边和一堆节点的集合,不过本题解不使用这样的集合,而是将图理解为一堆节点连接的一堆节点,即为List<List<Integer>>结构,外层的List包含了所有的节点,内层的List包含的这个节点指向的所有节点。在构建图时,获取图中的每条边,将边的终点加入 边的始点所指向的节点集合 中。

获取图中每个节点的入度很简单,只需要在构建图时,对于每条边,将终点的入度加一即可。

现在的问题就只剩下如何寻找边了,题目中提到prerequisites[i] = [a, b] 表示如果要学习课程 a必须 先学习课程 b,这句话说明prerequisites[i]数组为图中的一条边,第一个元素为 终点,第二个元素为 始点。

代码

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        // 初始化存储图的数据结构
        List<List<Integer>> graph = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) {
            graph.add(new ArrayList<>());
        }

        // 统计每个节点的入度,并构建图
        int[] inDegree = new int[numCourses]; // 存储每个节点的入度
        for (int[] pair : prerequisites) {
            int start = pair[1]; // 始点
            int end = pair[0]; // 终点
            List<Integer> toList = graph.get(start); // 获取 始点的 指向节点集合
            toList.add(end); // 将 终点 加入 始点的 指向节点集合 中
            inDegree[end]++; // 让终点的入度加一
        }

        // 寻找入度为0的节点,初始化队列
        LinkedList<Integer> queue = new LinkedList<>();
        for (int i = 0; i < inDegree.length; i++) {
            if (inDegree[i] == 0) { // 如果索引为i的节点的入度为0
                queue.offer(i); // 则将索引i放入队列
            }
        }

        // 拓扑排序
        int cnt = 0; // 统计移出队列的节点
        while (!queue.isEmpty()) { // 直到队列为空才退出循环
            cnt++;
            int start = queue.poll(); // 将节点移出队列,获取始点在graph中的索引
            List<Integer> toList = graph.get(start); // 获取始点指向的所有终点的索引
            for (int end : toList) { // 将始点指向的所有终点的入度减一
                if (--inDegree[end] == 0) { // 当终点的入度减到0时
                    queue.offer(end); // 将其加入队列
                }
            }
        }
        
        return cnt == numCourses; // 返回移出队列的节点数 是否等于 节点总数
    }
}

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

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

相关文章

《python程序语言设计》2018版第5章第53题利用turtle绘制sin和cos函数 sin蓝色,cos红色和52题类似

直接上题和代码 5.53 &#xff08;Turtle&#xff1a;绘制sin和cos函数&#xff09;编写程序绘制蓝色的sin函数和红色的cos函数。 代码和结果 turtle.speed(10) turtle.penup() # sin 用蓝色 turtle.color("blue") #这道题和上道题一样&#xff0c;先把turtle放到起始…

pandas读取CSV格式文件生成数据发生器iteration

背景 数据集标签为csv文件格式&#xff0c;有三个字段column_hander [‘id’, ‘boneage’, ‘male’]&#xff0c;需要自己定义数据集。文件较大&#xff0c;做一个数据发生器迭代更新数据集。 实现模板 在Pandas中&#xff0c;可以使用pandas.read_csv函数读取CSV文件&…

官网首屏:激发你的小宇宙和第六感,为了漂亮,干就完了。

官网的首屏是指用户打开网站后首先看到的页面&#xff0c;通常是整个网站最重要的一部分。首屏的设计和内容对于吸引用户的注意力、传达品牌形象和价值、促使用户继续浏览和进行交互非常关键。以下是官网首屏的重要性的几个方面&#xff1a; 1. 第一印象&#xff1a; 首屏是用…

Redis官方可视化管理工具

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl RedisInsight是一个Redis可视化工具&#xff0c;提供设计、开发和优化 Redis 应用程序的功能。RedisInsight分为免费的社区版和一个付费的企业版&#xff0c;免费版具有基本…

文心一言 VS 讯飞星火 VS chatgpt (297)-- 算法导论22.1 1题

一、给定有向图的邻接链表&#xff0c;需要多长时间才能计算出每个结点的出度(发出的边的条数)&#xff1f;多长时间才能计算出每个结点的入度(进入的边的条数)&#xff1f;如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 计算出度 对于有向图的邻接链表表示&a…

C++ 引用——常量引用

作用&#xff1a;常量引用主要用来修饰形参&#xff0c;防止误操作 在函数形参列表中&#xff0c;可以加const修饰形参&#xff0c;防止形参改变实参 示例&#xff1a; 运行结果&#xff1a;

【Linux】进程优先级 + 环境变量

前言 在了解进程状态之后&#xff0c;本章我们将来学习一下进程优先级&#xff0c;还有环境变量等。。 目录 1.进程优先级1.1 为什么要有优先级&#xff1f; 2.进程的其他概念2.1 竞争性与独立性2.2 并行与并发2.3 进程间优先级的体现&#xff1a;2.3.1 O(1) 调度算法&#xf…

202406 CCF-GESP Python 四级试题及详细答案注释

202406 CCF-GESP Python 四级试题及详细答案注释 1 单选题(每题 2 分,共 30 分)第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证考试的第1级,那他可以选择的认证语言有几种?( ) A. 1 B. 2 C. 3 D. 4答案:C解析:目前CCF组织的GESP认证考试有C++、Pyth…

Element中的表格组件Table和分页组件Pagination

简述&#xff1a;在 Element UI 中&#xff0c;Table组件是一个功能强大的数据展示工具&#xff0c;用于呈现结构化的数据列表。它提供了丰富的特性&#xff0c;使得数据展示不仅美观而且高效。而Pagination组件是一个用于实现数据分页显示的强大工具。它允许用户在大量数据中导…

【OJ】运行时错误(Runtime Error)导致递归爆栈问题

在进行OJ赛时&#xff0c; 题目&#xff1a;给你一个整数n&#xff0c;问最多能将其分解为多少质数的和。在第一行输出最多的质数数量k,下一行输出k个整数&#xff0c;为这些质数。 出现运行时错误 代码如下&#xff1a; def main():# code heren int(eval(input()))list …

RabbitMQ中常用的三种交换机【Fanout、Direct、Topic】

目录 1、引入 2、Fanout交换机 案例&#xff1a;利用SpringAMQP演示Fanout交换机的使用 3、Direct交换机 案例&#xff1a;利用SpringAMQP演示Direct交换机的使用 4、Topic交换机 案例&#xff1a;利用SpringAMQP演示Topic交换机的使用 1、引入 真实的生产环境都会经过e…

Apache Seata分布式事务原理解析探秘

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 前言 fescar发布已有时日&#xff0c;分布式事务一直是业界备受关注的领域&#xff0c;fesca…

【Mysql】记录MySQL中常见的错误代码及可能原因

希望文章能给到你启发和灵感&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏 支持一下博主吧&#xff5e; 阅读指南 开篇说明一、基础环境说明1.1 硬件环境1.2 软件环境 二、常见的问题2.1 连接和认证相关2.2 权限相关2.3 表和数据操作相关2.4 资源限制和…

我使用HarmonyOs Next开发了b站的首页

1.实现效果展示&#xff1a; 2.图标准备 我使用的是iconfont图标&#xff0c;下面为项目中所使用到的图标 3. 代码 &#xff08;1&#xff09;Index.ets&#xff1a; import {InfoTop} from ../component/InfoTop import {InfoCenter} from ../component/InfoCenter import…

文章解读与仿真程序复现思路——太阳能学报EI\CSCD\北大核心《计及电-热-氢负荷与动态重构的主动配电网优化调度》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

Linux 搭建 Kafka 环境 - 详细教程

目录 一. Kafka介绍 1. 应用场景 2. 版本对比 二. Kafka安装 1. 前置环境 &#xff08;1&#xff09;安装JDK 2. 软件安装 &#xff08;3&#xff09;环境变量配置 &#xff08;3&#xff09;服务启动 三. Console测试 基础命令 &#xff08;1&#xff09;列出Kafk…

PLC电源模块

PM电源模块 为CPU信号模块及 其他的扩展设备、其他用电设备&#xff08;如传感器&#xff09;提供工作供电 接线和开关 状态显示 灯的闪烁示意看手册 PS电源模块 为CPU信号模块及其他的扩展设备提供工作供电。PS(System Power Supply) 外形与PM电源模块类似&#xff0c;状…

PLC【搭建服务端】

PLC搭建服务端 文章目录 PLC搭建服务端前言一、搭建PLC服务器二、打开ModSean32获取数据总结 前言 使用博图V16编写PLC搭建服务器&#xff0c;使用 ModSean32 读取其中数据 一、搭建PLC服务器 打开博图V16点击项目进行新建&#xff0c;编辑好项目名称、及项目路径&#xff0c…

Netty 启动源码阅读

文章目录 1. 入门2. Netty 代码实例3. Netty bind3.1 initAndRegister3.1.1 newChannel, 创建 NioServerSocketChannel3.1.2 init(channel); 初始化 NioServerSocketChannel3.1.3 register 注册channel 3.2 doBind0 绑定端口3.3 ServerBootstrapAcceptor 1. 入门 主从Reactor模…

MATLAB制作一个简单的函数绘制APP

制作一个函数绘制APP&#xff0c;输入函数以及左右端点&#xff0c;绘制出函数图像。 编写回调函数&#xff1a; 结果&#xff1a;