059拓扑排序
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768import java.util.ArrayList;class Solution {/*** 找到所有课程的正确学习顺序。* 这个问题可以建模为一个有向无环图(DAG)的拓扑排序问题。** @param numCourses 课程总数* @param prerequisites 先决条件数组,prerequisites[i] = [ai, bi] 表示学习课程 ai 之前必须先学习课程 bi* @return 课程的有效学习顺序,如果不存在(图中存在环),则返回一个空数组*/public int[] findOrder(int numCourses, int[][] prerequisites) {// 1. 建立邻接表(图)和入度表ArrayList<ArrayList<Integer>...
025堆结构和堆排序
堆(Heap)是什么?堆是一种特殊的完全二叉树,它满足以下两个关键性质: 结构性:它必须是一棵完全二叉树,这意味着除了最后一层,其他所有层都是完全满的,并且最后一层的节点都靠左排列。这种结构使得它可以用一个简单的数组来高效存储。堆序性:每个节点的值都必须满足特定的关系。大顶堆(Max-Heap):每个父节点的值都大于或等于其子节点的值。小顶堆(Min-Heap):每个父节点的值都小于或等于其子节点的值。 在数组中,如果节点从索引 1 开始,那么父子关系可以通过简单的公式计算: 父节点:i/2左孩子:2i右孩子:2i+1 时间复杂度Onlogn 用常量增倍法把n个数建立堆 上限是n个数依次进入 第n个高度logn 所以上限nlogn假设2n个数 是否以这个做下限 后n个数高度大于logn 为什么是上限也是下限 说明只能是它 输出前m个小的数 import java.util.Scanner; public class Main { // N: 堆的最大容量 // h: 存储堆元素的数组,索引从1开始 // size: 堆中当前元素的...
左程云019输入输出的处理
ACM 风格的 I/O 与内存管理在算法竞赛(ACM)中,程序的执行效率至关重要。除了算法复杂度,I/O 和内存管理的开销也对性能有着决定性的影响。ACM 风格的编程追求极致的效率,其核心在于 I/O 缓冲 和 静态内存分配。 高效 I/O:BufferedReader 与 Scanner 的对比在 Java 中,Scanner 类提供了一个便利的接口,但其内部实现涉及频繁的底层 I/O 操作。每次调用 Scanner.nextInt() 或 Scanner.next(),都可能触发一次对系统 I/O 流的访问,这带来了显著的性能开销。 相比之下,BufferedReader 采用了一种缓冲机制来优化 I/O 性能。它在内存中维护一个缓冲区(默认大小为 8KB),并一次性从底层数据源(如 System.in)读取一大块数据。后续的读取请求都在这个内存缓冲区内完成,从而显著减少了对底层 I/O 设备的访问次数。 同样,为了优化输出,ACM 风格的程序会使用 PrintWriter 或 Buffere...
ccf第33
相似度计算 这是一道简单的模拟读取两篇文章的所有单词。将所有单词转换为小写,以忽略大小写差异。对每篇文章的单词进行去重,得到两个独立的单词集合 A 和 B。计算集合 A 和 B 的交集大小 |A∩B|。计算集合 A 和 B 的并集大小 |A∪B|。 只要算相同的就可以了 a并b = a+b-a交b那就用set吧 import java.util.*; class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); // 1. 读取两篇文章的单词个数 int n = sc.nextInt(); int m = sc.nextInt(); // 读取换行符,避免影响后续读取 这个很关键 sc.nextLine(); // 2. 创建两个 Set,分别存储两篇文章的单词 Set<String> setA = new HashSet<>(); Set<String> setB = new Hash...
ccf第38次第2题
这道题是经典的bfs,可以走八个方向,所以定义方向数组,这个题唯一不一样的是初始的x,y 是类似于坐标轴的表示形式,需要先把xy换成平常的。 有几个细节点要注意1.起点入队的时候记得标记st数组2.ans初始为1 因为起点也算剩下的就是bfs的常规操作,在k>0的时候,先判断队列是否不为空,若不为空就取出队头,然后遍历下一个坐标点,符合条件的进行入队,并且ans++; import java.util.*; class Main { private static final int[][]D = {{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2}}; public static void main(String args[]) { Scanner sc = new Scanner(System.in); int n...
ccf备赛
Java算法:正态分布查表问题在这篇文章中,我将分享一个我解决正态分布查表问题的过程。这个过程中,我遇到了输入输出、本地测试和线上提交的种种挑战,并最终找到了完美的解决方案。 初版代码(标准输入)这是我最开始编写的,用于从标准输入(键盘)读取数据的代码。 package java001; import java.util.Scanner; public class ccf { public static void main(String [] args){ Scanner scanner = new Scanner(System.in); int k = scanner.nextInt(); for(int i=0;i<k;i++){ int m = scanner.nextInt(); int s = scanner.nextInt(); int n = scanner.nextInt(); int ms = (n-...
数学笔记
这是我的数学学习笔记…
KMP算法
关于 KMP 算法 核心思想KMP 算法(Knuth-Morris-Pratt)主要用于在一个长字符串(主串 haystack)中查找一个短字符串(模式串 needle)的出现位置 。它的核心思想是利用模式串自身的特点,避免不必要的回溯,从而提高匹配效率。 主要讲解 KMP 算法的两个关键部分:生成 next 数组(前缀表)和使用 next 数组进行匹配。 生成 next 数组我们要求模式串的 next 数组,其实求的就是在每个位置的最长公共前后缀的长度。 定义两个指针,l 是前缀指针,r 是后缀指针。我们要求模式串的 next 数组。 以 aaab 为例,令 l=0, r=1,然后开始遍历。 在 for 循环中,right 从 1 开始,left 从 0 开始 。 在 while 循环里,如果 left 位置的字符不等于 right 位置的字符,left 指针会回退到上一个匹配过的位置,即 left = next[left - 1]。这个回退操作是核心,它利用的是“相同前后缀的相同前后缀”思想,而不是简单地回到 0 。 如果 left 位置的字符与 right 位置的字符相等...
测试文章
这是一篇测试文章
