Java 常用 API 分类总结(算法竞赛考前速记篇)- 适用于算法竞赛(如 CCF CSP、蓝桥杯、NOI)

发布于:2025-06-09 ⋅ 阅读:(20) ⋅ 点赞:(0)

以下是Java 常用 API 的系统性总结,特别适用于算法竞赛(如 CCF CSP、蓝桥杯、NOI)场景。按照功能分类,并给出代表性方法及简要用法说明,方便复习与带入考场:


✅ Java 常用 API 分类总结(算法竞赛篇)

常见数据类型的数据范围与默认值

当然可以!以下是 Java 中常见数据类型的数据范围与默认值总结,适合你背诵、练习和面试使用:

✅ 一、Java 基本数据类型总结(8种)

类型 占用空间 范围(含正负) 默认值
byte 1 字节 -128 ~ 127 0
short 2 字节 -32,768 ~ 32,767 0
int 4 字节 -2³¹ ~ 2³¹-1(-2,147,483,648 ~ 2,147,483,647) 0
long 8 字节 -2⁶³ ~ 2⁶³-1(约 ±9 × 10¹⁸) 0L
float 4 字节 约 ±3.4 × 10³⁸(7位有效数字) 0.0f
double 8 字节 约 ±1.8 × 10³⁰⁸(15位有效数字) 0.0d
char 2 字节 0 ~ 65535(Unicode 字符) '\u0000'
boolean 1 位(JVM 按 1 字节处理) true / false false

✅ 二、常用封装类与常量(用于边界判断)

类型 最大值 最小值 示例
Integer Integer.MAX_VALUE = 2147483647 Integer.MIN_VALUE = -2147483648 int a = Integer.MAX_VALUE;
Long Long.MAX_VALUE = 9223372036854775807L Long.MIN_VALUE = -9223372036854775808L
Double Double.MAX_VALUE ≈ 1.79769e+308 Double.MIN_VALUE ≈ 4.9e-324(最小正数) 注意 Double.MIN_VALUE 是正数
Float Float.MAX_VALUE ≈ 3.40282e+38 Float.MIN_VALUE ≈ 1.4e-45 同上
Character Character.MAX_VALUE = 65535 ('\uffff') Character.MIN_VALUE = 0 ('\u0000')

✅ 三、如何选择数据类型?(实用建议)

场景 推荐类型 原因
统计、计数 int / long 小数据用 int,大数据(>10⁹)用 long
精确小数运算 BigDecimal 如货币计算,避免精度丢失
浮点计算 double 精度高于 float
布尔开关 boolean 性能优,语义清晰
单个字符 char 适合处理字符型数据

✅ 四、经典面试题:Integer.MIN_VALUE 的绝对值是多少?

System.out.println(Math.abs(Integer.MIN_VALUE)); // 输出仍为 -2147483648

这是因为 abs() 溢出!因为 -2147483648 没有正数对应(超出 int 正范围)。

✅ 五、背诵口诀助记法:

byte 短 short 刚好 32k,
int 四字节到 21亿。
long 八字节超千万亿,
float double 飘到天际。
char 是 Unicode,boolean 真或假。

1️⃣ 字符串处理(String 类)

方法 用途 示例
length() 获取字符串长度 "abc".length() -> 3
charAt(i) 获取索引 i 处字符 "abc".charAt(1) -> 'b'
substring(start, end) 截取子串(左闭右开) "abcdef".substring(1,4) -> "bcd"
indexOf(str) 第一次出现位置 "ababc".indexOf("ab") -> 0
lastIndexOf(str) 最后一次出现位置 "ababc".lastIndexOf("ab") -> 2
contains(str) 是否包含 "abc".contains("b") -> true
split(regex) 按正则分割为数组 "a,b,c".split(",") -> [a, b, c]
equals(str) 是否相等 "abc".equals("abc") -> true
compareTo(str) 字典序比较 "abc".compareTo("abd") -> -1
toCharArray() 转为字符数组 "abc" -> ['a','b','c']
replace(old, new) 替换子串 "aabb".replace("a", "c") -> "ccbb"
trim() 去除首尾空格 " a b ".trim() -> "a b"
toLowerCase() 转小写 "ABC".toLowerCase() -> "abc"
toUpperCase() 转大写 "abc".toUpperCase() -> "ABC"
startsWith(str) 以某串开头 "abc".startsWith("a") -> true
endsWith(str) 以某串结尾 "abc".endsWith("c") -> true

2️⃣ 高效字符串拼接(StringBuilder / StringBuffer

方法 用途
append(str) 添加字符串
insert(pos, str) 插入字符串
delete(start, end) 删除子串
reverse() 翻转字符串
toString() 转回字符串

⚠️ StringBuilder 非线程安全,StringBuffer 线程安全(但慢)。


3️⃣ 数学计算(Math 类)

方法 说明
abs(x) 绝对值
max(a, b) / min(a, b) 最大 / 最小值
pow(a, b) a 的 b 次幂
sqrt(x) 平方根
cbrt(x) 立方根
ceil(x) 向上取整
floor(x) 向下取整
round(x) 四舍五入(返回 long
random() 返回 [0,1) 间随机数
log(x) / log10(x) 自然对数 / 常用对数
sin(x), cos(x), tan(x) 三角函数(弧度)

4️⃣ 数组处理(Arrays 工具类)

方法 说明
sort(array) 升序排序
binarySearch(array, key) 二分查找(有序数组)
fill(array, val) 全部填充为 val
copyOf(arr, newLen) 拷贝前 newLen 个元素
equals(a, b) 比较两个数组是否完全相等
toString(arr) 数组转字符串
asList(T... arr) 数组转固定长度 List

5️⃣ 集合框架

List(ArrayList / LinkedList

方法 说明
add(e) 添加元素
remove(i) 删除索引 i 元素
get(i) 获取元素
set(i, e) 修改元素
size() 获取大小
contains(e) 是否包含元素

Set(HashSet / TreeSet

方法 说明
add(e) 添加元素
remove(e) 移除元素
contains(e) 是否存在
size() 元素个数
first() / last() TreeSet 中的最小 / 最大值
ceiling(e) ≥e 的最小值
floor(e) ≤e 的最大值

✅ 一、常见 Set 实现类对比

类名 是否有序 是否允许 null 是否线程安全 底层结构
HashSet ❌ 无序 ✅ 允许一个 ❌ 不安全 哈希表
LinkedHashSet ✅ 插入顺序 ✅ 允许一个 ❌ 不安全 哈希表 + 双向链表
TreeSet ✅ 升序 ❌ 不允许 ❌ 不安全 红黑树(平衡二叉树)

✅ 二、常用 Set API 汇总

功能 示例代码 说明
初始化 Set<Integer> set = new HashSet<>(); 常用 HashSet
添加元素 set.add(x); 添加元素(若重复则不变)
删除元素 set.remove(x); 删除元素(若无也不报错)
是否包含 set.contains(x); 判断元素是否存在
获取大小 set.size(); 元素个数
清空集合 set.clear(); 清空所有元素
是否为空 set.isEmpty(); 是否为空
遍历元素 for (int x : set) 常用 for-each 遍历
转为 List new ArrayList<>(set); 若需排序或索引操作
集合并集(新增) set.addAll(otherSet); 将另一个集合元素加入本集合
集合交集(保留) set.retainAll(otherSet); 只保留两集合都存在的元素
集合差集(去除) set.removeAll(otherSet); 去除在 otherSet 中也有的元素

✅ 三、典型代码模板

📌 1. 初始化 + 去重存储

Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(2); // 无效重复
System.out.println(set); // 输出 [1, 2]

📌 2. 遍历 + 判断是否存在

for (int x : set) {
    if (x == 3) System.out.println("存在");
}

📌 3. 使用 TreeSet 实现自动排序

Set<String> treeSet = new TreeSet<>();
treeSet.add("banana");
treeSet.add("apple");
System.out.println(treeSet); // [apple, banana]

✅ 四、适配题型速查

题型类别 用法建议 举例题目
去重统计 HashSet 存入后 size() [CSP] 数字种类、集合大小
判断是否重复 set.contains(x) + set.add(x) 力扣 217、219
保持顺序去重 LinkedHashSet 输出按插入顺序的唯一值序列
需要有序输出 TreeSet + 自动排序 力扣 349、350(交集类)

✅ 五、背诵口诀:“增删查,去重快,TreeSet 排序不带盖!”

✅ 六、你可以练习的题目(推荐)

平台 题目 ID / 名称 涉及 API
力扣 217. 存在重复元素 set.contains()
力扣 349. 两个数组的交集 set.retainAll()
力扣 705. 设计哈希集合 手写 Set 底层结构
CSP 出现过的数、不同的数种类统计 set.add() + set.size()

Map(HashMap / TreeMap

方法 说明
put(key, val) 添加键值对
get(key) 获取值(无则返回 null)
getOrDefault(key, def) 若无该 key,返回默认值
containsKey(key) 是否包含键
keySet() 所有 key 集合
values() 所有 value
entrySet() 所有 entry(用于遍历)

频次统计(CSP常见)

map.put(x, map.getOrDefault(x, 0) + 1);

6️⃣ Collections 工具类(操作集合)

方法 说明
sort(list) 升序排序
reverse(list) 反转列表
shuffle(list) 随机打乱
frequency(list, obj) 统计出现次数
swap(list, i, j) 交换元素
rotate(list, k) 向右旋转 k 位
max(list) / min(list) 最大 / 最小值

7️⃣ 优先队列(PriorityQueue

PriorityQueue<Integer> pq = new PriorityQueue<>(); // 默认小根堆
pq.offer(3); pq.offer(1); pq.offer(2);
pq.peek(); // 1
pq.poll(); // 弹出最小的 1

自定义大根堆:

PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);

8️⃣ 位运算(Integer 类)

方法 说明
bitCount(i) 二进制中 1 的个数
highestOneBit(i) 最高位的 1 的值(如 1000)
lowestOneBit(i) 最低位的 1 的值(如 0001)
toBinaryString(i) 二进制表示
parseInt(s, radix) 任意进制转十进制
toHexString(i) 十六进制表示

9️⃣ 大数处理

BigInteger

方法 说明
add() / subtract() / multiply() / divide() 四则运算
mod() 取模
pow(n)
compareTo(BigInteger) 比较大小
gcd() 最大公约数
isProbablePrime(certainty) 判断素数(概率)
BigInteger a = new BigInteger("123456789");
BigInteger b = new BigInteger("987654321");
a.add(b).toString(); // 字符串输出

BigDecimal

方法 说明
add(), subtract(), multiply(), divide() 高精度小数运算
setScale(n, RoundingMode) 设置小数位数
compareTo() 比较大小

🔟 时间函数

方法 说明
System.currentTimeMillis() 当前毫秒时间戳
System.nanoTime() 纳秒时间戳(高精度测时)
LocalDateTime.now() 当前时间
ChronoUnit.SECONDS.between(start, end) 时间间隔

🔟+1 正则表达式处理

方法
Pattern.compile(regex) 编译正则
matcher(str) 创建匹配器
find() / group() 匹配和提取子串
matches() 整体匹配是否成功

🔟+2 输入输出(Scanner, BufferedReader, PrintWriter

方法
Scanner next(), nextLine(), nextInt()
BufferedReader 高效读取(支持 readLine()
PrintWriter 快速输出,println()flush()
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
String s = br.readLine();
out.println(s);
out.flush();

常考模块

自定义排序

你提的问题非常好!作为初学者,理解 Arrays.sort()Collections.sort()区别与适用场景,对于写出更规范、稳定、灵活的排序代码至关重要。以下是详细解释和通用解法整理👇

✅ 一、Arrays.sort()Collections.sort() 有什么区别?

比较点 Arrays.sort() Collections.sort()
适用对象 数组(如 int[]String[]Integer[] List(如 ArrayListLinkedList
所在包 java.util.Arrays java.util.Collections
排序方式 默认升序;支持传入比较器 Comparator 默认升序;也支持传入比较器 Comparator
是否稳定排序 对对象数组使用 TimSort(稳定) 使用 List.sort(),底层同样是 TimSort(稳定)
是否可以混用 ❌ 不可以直接混用 ListCollections.sort() 是配套的

🚫 不可以这样混用:

List<Integer> list = new ArrayList<>();
Arrays.sort(list); // ❌ 错误,Arrays.sort 不能用于 List

✅ 正确用法:

int[] arr = new int[]{5, 2, 3};
Arrays.sort(arr); // 用于基本类型数组

List<Integer> list = new ArrayList<>(List.of(5, 2, 3));
Collections.sort(list); // 用于 List

✅ 二、二者的典型应用对比

🧩 排序数组 → 用 Arrays.sort()

int[] arr = {4, 2, 9};
Arrays.sort(arr); // 升序:[2, 4, 9]

🧩 排序对象数组 → 仍用 Arrays.sort()

Student[] stu = ...;
Arrays.sort(stu, (a, b) -> b.score - a.score); // 按成绩降序

🧩 排序 List → 用 Collections.sort() 或 Java 8 的 list.sort()

List<String> list = new ArrayList<>(List.of("cat", "apple", "banana"));
Collections.sort(list); // 默认字典序

等价于 Java 8 写法:

list.sort(String::compareTo); // 同样是字典序

✅ 三、是否可以用 Collections.sort() 替代 Arrays.sort()

🟡 不能直接替代! 因为它们的参数类型不同!

  • Arrays.sort() 适用于 数组(如 int[], Integer[], String[] 等)
  • Collections.sort() 适用于 List(如 ArrayList, LinkedList

但你可以将数组转成 List 来使用 Collections.sort()(用于对象类型数组):

✅ 数组转 List 再排序(适用于对象数组)

Integer[] arr = {5, 2, 9};
List<Integer> list = Arrays.asList(arr);
Collections.sort(list); // 排序后 arr 也变化(共享内存)

⚠️ 注意: Arrays.asList() 返回的是一个固定长度的列表,不能增删元素,只能排序或修改已有元素。

✅ 四、初学者建议记忆总结

想排序什么? 用什么? 支持自定义比较器? 是否稳定?
int[] / double[] Arrays.sort()
Integer[] / 对象数组 Arrays.sort(arr, cmp)
List(ArrayList) Collections.sort() / list.sort()
Map 转为 entrySet() 的 List 后排序

✨ 五、通用排序封装函数(建议记忆)

// 通用对象排序(List)
public static <T> void sortList(List<T> list, Comparator<T> cmp) {
    Collections.sort(list, cmp);
}

// 通用数组排序(对象数组)
public static <T> void sortArray(T[] arr, Comparator<T> cmp) {
    Arrays.sort(arr, cmp);
}

在 Java 中进行“自定义排序”,常用于对数组、对象集合(如 List)等进行灵活的排序。CSP 考试中,常见场景包括:

  • 对多个字段排序(如先按成绩,再按学号)
  • 自定义结构(如 Pair)排序
  • 降序 / 升序控制

✅ 一、对数组进行自定义排序(基本类型)

import java.util.*;

public class CustomSortArray {
    public static void main(String[] args) {
        Integer[] arr = {5, 2, 8, 1, 9};

        // 降序排序
        Arrays.sort(arr, (a, b) -> b - a);

        System.out.println(Arrays.toString(arr)); // [9, 8, 5, 2, 1]
    }
}

注意:int[] 不能直接使用 Lambda 表达式,必须使用 Integer[] 对象数组。

✅ 二、自定义结构排序(如 Pair)

import java.util.*;

class Pair {
    int id, score;

    public Pair(int id, int score) {
        this.id = id;
        this.score = score;
    }

    @Override
    public String toString() {
        return "(" + id + "," + score + ")";
    }
}

public class CustomSortPair {
    public static void main(String[] args) {
        List<Pair> list = new ArrayList<>();
        list.add(new Pair(1, 90));
        list.add(new Pair(3, 80));
        list.add(new Pair(2, 90));

        // 排序规则:先按 score 降序,再按 id 升序
        Collections.sort(list, (a, b) -> {
            if (a.score != b.score) return b.score - a.score; // 降序
            return a.id - b.id; // 升序
        });

        for (Pair p : list) {
            System.out.println(p);
        }
    }
}

✅ 三、二维数组排序(常见于模拟/DP)

import java.util.*;

public class CustomSort2DArray {
    public static void main(String[] args) {
        int[][] data = {
            {1, 90},
            {2, 100},
            {3, 90}
        };

        // 按第二列降序,再按第一列升序
        Arrays.sort(data, (a, b) -> {
            if (a[1] != b[1]) return b[1] - a[1];
            return a[0] - b[0];
        });

        for (int[] row : data) {
            System.out.println(Arrays.toString(row));
        }
    }
}

✅ 四、优先队列中的自定义排序(堆)

import java.util.*;

public class CustomPriorityQueue {
    public static void main(String[] args) {
        // 最小堆按第一维升序,第二维降序
        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> {
            if (a[0] != b[0]) return a[0] - b[0];
            return b[1] - a[1];
        });

        pq.offer(new int[]{2, 100});
        pq.offer(new int[]{1, 80});
        pq.offer(new int[]{2, 90});

        while (!pq.isEmpty()) {
            System.out.println(Arrays.toString(pq.poll()));
        }
    }
}

📌 总结:常用模板

// Arrays.sort + Lambda
Arrays.sort(array, (a, b) -> {
    // 优先级:先按某字段,再按其他字段
    return a[0] - b[0]; // 升序 / b[0] - a[0] 降序
});

// List + Collections.sort
Collections.sort(list, (a, b) -> {
    if (a.score != b.score) return b.score - a.score;
    return a.id - b.id;
});

// PriorityQueue + 自定义比较器
PriorityQueue<Node> pq = new PriorityQueue<>((a, b) -> a.weight - b.weight);

以下是为 CCF CSP 考试 精心整理的「常见排序题速查表」,包含常考题型、解题策略、排序维度、API 示例等,帮助你快速定位解题方案。

✅ 一、速查表概览(按题型分类)

题型类别 排序关键 排序维度 示例题目 典型排序语句
成绩/统计排序 值大小 降序或多字段 成绩排序、热度统计等 Collections.sort(list, (a,b)->b.score-a.score)
时间线排序 时间戳 升序 日志记录、任务调度等 Arrays.sort(arr, Comparator.comparingInt(a -> a.time))
坐标排序 x/y轴 多字段(先 x 后 y) 坐标扫描、区间合并等 Arrays.sort(points, (a,b)->a[0]==b[0]?a[1]-b[1]:a[0]-b[0])
编号优先 编号 按编号升序 按原始输入顺序输出 Collections.sort(list, Comparator.comparingInt(a->a.id))
并查集/连通块 集合大小 降序或升序 连通块排序输出 自定义结构 + 统计 + 排序
哈希计数 次数 降序 + 值本身升序 频率统计、单词计数等 统计完后 List<Map.Entry> 排序

✅ 二、各类型题型详解与模板

1️⃣ 成绩类排序(权重/成绩/频次)

例题:

  • 成绩排行
  • 词频统计
class Student {
    int id, score;
}

Collections.sort(list, (a, b) -> {
    if (a.score != b.score) return b.score - a.score;
    return a.id - b.id;
});

2️⃣ 时间类排序(时间戳、操作先后)

例题:

  • 日志排序
  • 任务调度优先队列
Arrays.sort(events, (a, b) -> a.time - b.time); // 按时间升序

或使用对象:

class Event {
    int time, id;
}
Collections.sort(list, Comparator.comparingInt(e -> e.time));

3️⃣ 坐标/区间排序

例题:

  • 扫描线、区间覆盖、最大重叠区间
Arrays.sort(intervals, (a, b) -> {
    if (a[0] != b[0]) return a[0] - b[0]; // 起点升序
    return a[1] - b[1];                   // 终点升序
});

4️⃣ Map排序(基于统计结果)

例题:

  • 词频统计
  • 热度排序
Map<Integer, Integer> count = new HashMap<>();
for (int x : arr) count.put(x, count.getOrDefault(x, 0) + 1);

List<Map.Entry<Integer, Integer>> list = new ArrayList<>(count.entrySet());

// 按频率降序、数值升序排序
Collections.sort(list, (a, b) -> {
    if (!a.getValue().equals(b.getValue()))
        return b.getValue() - a.getValue();
    return a.getKey() - b.getKey();
});

5️⃣ 并查集/连通块大小排序

例题:

  • 社交网络连通块分析
  • 亲戚关系等题
// 每个集合统计 size[]
// 然后将 size 按 root 排序
List<int[]> groups = new ArrayList<>();
for (int i = 1; i <= n; i++) {
    if (find(i) == i) groups.add(new int[]{i, size[i]});
}
groups.sort((a, b) -> b[1] - a[1]); // 按集合大小降序

6️⃣ 字典序排序(字符串或数组)

例题:

  • 最小字典序拼接
  • 拼接序列/排序
Arrays.sort(strings); // 默认字典序
Arrays.sort(strings, Comparator.reverseOrder()); // 字典序逆序

✅ 三、优先队列(堆)排序应用速查

需求类型 排序维度 声明语句
最小值优先队列 值升序 PriorityQueue<Integer> pq = new PriorityQueue<>();
最大值优先队列 值降序 PriorityQueue<Integer> pq = new PriorityQueue<>((a,b)->b-a);
多字段堆排序 数组 or 对象 PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)->{...});

✅ 四、常用 Java API 排序参考

用法 示例代码
数组默认排序 Arrays.sort(arr);
对象数组排序 Arrays.sort(objArr, (a, b) -> ...);
List 排序 Collections.sort(list, (a, b) -> ...);
Map 排序(按值) 见上面 Map 示例
PriorityQueue 自定义顺序 new PriorityQueue<>((a,b) -> ...)

📌 附:CCF CSP 排序常见题目清单(历年)

年份 题目名称 排序类型
202206 通信网络 拓扑序 / 时间戳
202012 直播获奖名单 词频统计 + 排序
201809 元素选择器 DOM序树结构排序
201712 游戏 结构排序 + 计分
201703 学生排队 优先队列 / 模拟

🔐 五、哈希/计数

  • HashMap, HashSet:用于快速查找
  • TreeMap, TreeSet:自动排序
  • Map.getOrDefault(k, v):避免空指针
  • int[] cnt = new int[m + 1];:模拟 HashMap 的计数数组,常用于编号有限的场景(如 CSP)

🧩 六、模拟题常用

  • Scanner:快速读入
  • StringTokenizer(复杂输入场景)或 BufferedReader
  • 多维数组处理:int[][] arr = new int[n][m];
  • 模拟移动:方向数组 dx/dy

🔄 七、并查集(Union-Find)

int[] fa = new int[n];
for (int i = 0; i < n; i++) fa[i] = i;

int find(int x) { return fa[x] == x ? x : (fa[x] = find(fa[x])); }

void union(int x, int y) { fa[find(x)] = find(y); }

🌉 八、图论常用

✅ 图存储
  • 邻接表:List<List<Integer>> graph = new ArrayList<>();
  • 邻接矩阵:int[][] graph = new int[n][n];
✅ 遍历
  • DFS / BFS 模板
  • Queue<Integer> q = new LinkedList<>();

📐 九、动态规划(DP)

  • 通常使用 int[], int[][] 进行状态压缩或转移
  • 可用 Arrays.fill() 进行初始化
  • 多维数组状态转移举例:
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]);

💡 十、贪心算法

  • 常用 Arrays.sort()Collections.sort() 后进行策略判断
  • 自定义排序:
Arrays.sort(arr, (a, b) -> a[0] - b[0]);
  • 优先队列(堆):
PriorityQueue<Integer> pq = new PriorityQueue<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
pq.offer(x); pq.poll(); pq.peek();

🧮 十一、常用工具类

功能 API
比较两个对象 Objects.equals(a, b)
大整数运算 BigInteger(如加减乘除、取模、幂)
高精度小数 BigDecimal

Java API 使用示例代码

当然可以,下面我将针对 CSP 常考模块(字符串处理、模拟、哈希、排序、并查集、图、DP、贪心)分别提供一两个典型题目的Java API 使用示例代码,方便你快速上手实战题目。


✅ 一、字符串处理 - 示例题:“单词统计”

题目描述:给定一段英文文本,统计不同单词出现次数(不区分大小写,去除标点)。

import java.util.*;

public class WordCount {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String text = sc.nextLine().toLowerCase().replaceAll("[^a-z ]", " ");
        String[] words = text.split("\\s+");

        Map<String, Integer> count = new HashMap<>();
        for (String word : words) {
            if (!word.isEmpty()) {
                count.put(word, count.getOrDefault(word, 0) + 1);
            }
        }

        count.forEach((k, v) -> System.out.println(k + ": " + v));
    }
}

✅ 二、模拟 - 示例题:“排队打水”

题目描述:n 个人排队,每个人打水需要 t[i] 分钟,问最小总等待时间。

import java.util.*;

public class WaterQueue {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] t = new int[n];
        for (int i = 0; i < n; i++) t[i] = sc.nextInt();
        Arrays.sort(t); // 排序是贪心核心

        long res = 0;
        for (int i = 0; i < n; i++) {
            res += (long) t[i] * (n - i - 1); // 模拟等待时间
        }

        System.out.println(res);
    }
}

✅ 三、哈希 - 示例题:“出现次数统计”

题目描述:输入 n 个整数,输出每个数的出现次数。

import java.util.*;

public class FrequencyCount {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            int x = sc.nextInt();
            map.put(x, map.getOrDefault(x, 0) + 1);
        }

        for (int key : map.keySet()) {
            System.out.println(key + ": " + map.get(key));
        }
    }
}

✅ 四、排序 - 示例题:“按得分排序”

题目描述:输入学生姓名与分数,按分数从高到低排序输出。

import java.util.*;

public class ScoreSort {
    static class Student {
        String name; int score;
        Student(String n, int s) { name = n; score = s; }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        List<Student> list = new ArrayList<>();
        for (int i = 0; i < n; i++)
            list.add(new Student(sc.next(), sc.nextInt()));

        list.sort((a, b) -> b.score - a.score); // 自定义排序

        for (Student s : list)
            System.out.println(s.name + " " + s.score);
    }
}

✅ 五、并查集 - 示例题:“朋友圈数量”

题目描述:有 n 个人,m 对朋友关系,问总共有多少个朋友圈(连通块)。

import java.util.*;

public class UnionFindFriends {
    static int[] fa;
    static int find(int x) {
        if (fa[x] != x) fa[x] = find(fa[x]);
        return fa[x];
    }

    static void union(int x, int y) {
        fa[find(x)] = find(y);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt();
        fa = new int[n + 1];
        for (int i = 1; i <= n; i++) fa[i] = i;

        for (int i = 0; i < m; i++) union(sc.nextInt(), sc.nextInt());

        Set<Integer> roots = new HashSet<>();
        for (int i = 1; i <= n; i++) roots.add(find(i));

        System.out.println(roots.size()); // 连通块个数
    }
}

✅ 六、图 - 示例题:“最短路径 BFS”

题目描述:无权图从点 A 到点 B 的最短路径长度。

import java.util.*;

public class BFSShortestPath {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt();
        List<List<Integer>> g = new ArrayList<>();
        for (int i = 0; i <= n; i++) g.add(new ArrayList<>());
        for (int i = 0; i < m; i++) {
            int u = sc.nextInt(), v = sc.nextInt();
            g.get(u).add(v); g.get(v).add(u);
        }

        int[] dist = new int[n + 1];
        Arrays.fill(dist, -1);
        Queue<Integer> q = new LinkedList<>();
        q.offer(1); dist[1] = 0;

        while (!q.isEmpty()) {
            int cur = q.poll();
            for (int nei : g.get(cur)) {
                if (dist[nei] == -1) {
                    dist[nei] = dist[cur] + 1;
                    q.offer(nei);
                }
            }
        }

        System.out.println(dist[n]);
    }
}

✅ 七、动态规划(DP)- 示例题:“背包问题”

import java.util.*;

public class ZeroOneKnapsack {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), W = sc.nextInt();
        int[] w = new int[n + 1], v = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            w[i] = sc.nextInt(); v[i] = sc.nextInt();
        }

        int[] dp = new int[W + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = W; j >= w[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]);
            }
        }

        System.out.println(dp[W]);
    }
}

✅ 八、贪心 - 示例题:“活动安排问题”

题目描述:选择最多不重叠的活动。

import java.util.*;

public class GreedyActivitySelect {
    static class Act {
        int start, end;
        Act(int s, int e) { start = s; end = e; }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        List<Act> list = new ArrayList<>();
        for (int i = 0; i < n; i++)
            list.add(new Act(sc.nextInt(), sc.nextInt()));

        list.sort(Comparator.comparingInt(a -> a.end)); // 按结束时间排序

        int cnt = 0, lastEnd = 0;
        for (Act a : list) {
            if (a.start >= lastEnd) {
                cnt++; lastEnd = a.end;
            }
        }

        System.out.println(cnt);
    }
}

蓝桥杯万字攻略:算法模板大放送!-Java 版

主要内容

由数据范围反推算法复杂度以及算法内容

一般ACM或者笔试题的时间限制是1秒或2秒。在这种情况下,Java代码中的操作次数控制在 (10^7 \sim 10^8) 为最佳。

下面给出在不同数据范围下,代码的时间复杂度和算法该如何选择:

数据范围 时间复杂度 算法
(n \le 30) 指数级别 dfs+剪枝,状态压缩dp
(n \le 100) (O(n^3)) Floyd,dp,高斯消元
(n \le 1000) (O(n2)),(O(n2logn)) dp,二分,朴素版Dijkstra、朴素版Prim、Bellman-Ford
(n \le 10000) (O(n * \sqrt n)) 块状链表、分块、莫队
(n \le 100000) (O(nlogn)) 各种sort,线段树、树状数组、set/map、heap、拓扑排序、dijkstra+heap、prim+heap、Kruskal、spfa、求凸包、求半平面交、二分、CDQ分治、整体二分、后缀数组、树链剖分、动态树
(n \le 1000000) (O(n)), 以及常数较小的 (O(nlogn)) 算法 单调队列、 hash、双指针扫描、并查集,kmp、AC自动机,常数比较小的 (O(nlogn)) 的做法:sort、树状数组、heap、dijkstra、spfa
(n \le 10000000) (O(n)) 双指针扫描、kmp、AC自动机、线性筛素数
(n \le 10^9) (O(\sqrt n)) 判断质数
(n \le 10^{18}) (O(logn)) 最大公约数,快速幂,数位DP
(n \le 10^{1000}) (O((logn)^2)) 高精度加减乘除
(n \le 10^{100000}) (O(logk \times loglogk),k表示位数) 高精度加减、FFT/NTT 由数据范围反推算法

基础算法

快速排序算法模板
import java.util.Arrays;

public class QuickSort {
    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pi = partition(arr, low, high);
            quickSort(arr, low, pi - 1);
            quickSort(arr, pi + 1, high);
        }
    }

    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[low + (high - low) / 2];
        int i = low - 1;
        int j = high + 1;
        while (true) {
            while (arr[++i] < pivot);
            while (arr[--j] > pivot);
            if (i >= j) {
                return j;
            }
            swap(arr, i, j);
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}
归并排序算法模板
import java.util.Arrays;

public class MergeSort {
    private static int[] temp;

    public static void mergeSort(int[] arr) {
        temp = new int[arr.length];
        mergeSort(arr, 0, arr.length - 1);
    }

    private static void mergeSort(int[] arr, int l, int r) {
        if (l >= r) {
            return;
        }
        int mid = l + (r - l) / 2;
        mergeSort(arr, l, mid);
        mergeSort(arr, mid + 1, r);
        merge(arr, l, mid, r);
    }

    private static void merge(int[] arr, int l, int mid, int r) {
        System.arraycopy(arr, l, temp, l, r - l + 1);
        int i = l, j = mid + 1, k = l;
        while (i <= mid && j <= r) {
            if (temp[i] <= temp[j]) {
                arr[k++] = temp[i++];
            } else {
                arr[k++] = temp[j++];
            }
        }
        while (i <= mid) {
            arr[k++] = temp[i++];
        }
        while (j <= r) {
            arr[k++] = temp[j++];
        }
    }
}
整数二分算法模板
public class BinarySearch {
    public static int bsearch_1(int[] arr, int target) {
        int l = 0, r = arr.length - 1;
        while (l < r) {
            int mid = l + (r - l) / 2;
            if (arr[mid] >= target) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }

    public static int bsearch_2(int[] arr, int target) {
        int l = 0, r = arr.length - 1;
        while (l < r) {
            int mid = l + (r - l + 1) / 2;
            if (arr[mid] <= target) {
                l = mid;
            } else {
                r = mid - 1;
            }
        }
        return l;
    }
}
浮点数二分算法模板
public class BinarySearchFloat {
    public static double bsearch_3(double l, double r) {
        final double eps = 1e-6;
        while (r - l > eps) {
            double mid = (l + r) / 2;
            if (check(mid)) {
                r = mid;
            } else {
                l = mid;
            }
        }
        return l;
    }

    private static boolean check(double x) {
        return false;
    }
}
高精度加法
import java.util.ArrayList;
import java.util.List;

public class HighPrecisionAddition {
    public static List<Integer> add(List<Integer> A, List<Integer> B) {
        if (A.size() < B.size()) {
            return add(B, A);
        }

        List<Integer> C = new ArrayList<>();
        int t = 0;
        for (int i = 0; i < A.size(); i++) {
            t += A.get(i);
            if (i < B.size()) {
                t += B.get(i);
            }
            C.add(t % 10);
            t /= 10;
        }

        if (t != 0) {
            C.add(t);
        }

        while (C.size() > 1 && C.get(C.size() - 1) == 0) {
            C.remove(C.size() - 1);
        }

        return C;
    }
}
高精度减法
import java.util.ArrayList;
import java.util.List;

public class HighPrecisionSubtraction {
    public static List<Integer> sub(List<Integer> A, List<Integer> B) {
        List<Integer> C = new ArrayList<>();
        int t = 0;
        for (int i = 0; i < A.size(); i++) {
            t = A.get(i) - t;
            if (i < B.size()) {
                t -= B.get(i);
            }
            C.add((t + 10) % 10);
            if (t < 0) {
                t = 1;
            } else {
                t = 0;
            }
        }

        while (C.size() > 1 && C.get(C.size() - 1) == 0) {
            C.remove(C.size() - 1);
        }

        return C;
    }
}
高精度乘低精度
import java.util.ArrayList;
import java.util.List;

public class HighPrecisionMultiplication {
    public static List<Integer> mul(List<Integer> A, int b) {
        List<Integer> C = new ArrayList<>();

        int t = 0;
        for (int i = 0; i < A.size() || t != 0; i++) {
            if (i < A.size()) {
                t += A.get(i) * b;
            }
            C.add(t % 10);
            t /= 10;
        }

        while (C.size() > 1 && C.get(C.size() - 1) == 0) {
            C.remove(C.size() - 1);
        }

        return C;
    }
}
高精度除以低精度
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class HighPrecisionDivision {
    public static List<Integer> div(List<Integer> A, int b, int[] r) {
        List<Integer> C = new ArrayList<>();
        int remainder = 0;
        for (int i = A.size() - 1; i >= 0; i--) {
            remainder = remainder * 10 + A.get(i);
            C.add(remainder / b);
            remainder %= b;
        }
        Collections.reverse(C);
        while (C.size() > 1 && C.get(C.size() - 1) == 0) {
            C.remove(C.size() - 1);
        }
        r[0] = remainder;
        return C;
    }
}
一维前缀和
import java.util.ArrayList;
import java.util.List;

public class PrefixSum1D {
    public static List<Integer> getPrefixSum(List<Integer> arr) {
        List<Integer> prefixSum = new ArrayList<>();
        prefixSum.add(0);
        for (int num : arr) {
            prefixSum.add(prefixSum.get(prefixSum.size() - 1) + num);
        }
        return prefixSum;
    }

    public static int querySum(List<Integer> prefixSum, int l, int r) {
        return prefixSum.get(r) - prefixSum.get(l - 1);
    }
}
二维前缀和
import java.util.ArrayList;
import java.util.List;

public class PrefixSum2D {
    public static List<List<Integer>> getPrefixSum(List<List<Integer>> matrix) {
        int rows = matrix.size();
        int cols = matrix.get(0).size();
        List<List<Integer>> prefixSum = new ArrayList<>();
        for (int i = 0; i <= rows; i++) {
            List<Integer> row = new ArrayList<>();
            for (int j = 0; j <= cols; j++) {
                row.add(0);
            }
            prefixSum.add(row);
        }

        for (int i = 1; i <= rows; i++) {
            for (int j = 1; j <= cols; j++) {
                prefixSum.get(i).set(j, matrix.get(i - 1).get(j - 1) + prefixSum.get(i - 1).get(j) + prefixSum.get(i).get(j - 1) - prefixSum.get(i - 1).get(j - 1));
            }
        }

        return prefixSum;
    }

    public static int querySum(List<List<Integer>> prefixSum, int x1, int y1, int x2, int y2) {
        return prefixSum.get(x2).get(y2) - prefixSum.get(x1 - 1).get(y2) - prefixSum.get(x2).get(y1 - 1) + prefixSum.get(x1 - 1).get(y1 - 1);
    }
}
一维差分
import java.util.ArrayList;
import java.util.List;

public class Difference1D {
    public static List<Integer> getDifference(List<Integer> arr) {
        List<Integer> diff = new ArrayList<>();
        diff.add(arr.get(0));
        for (int i = 1; i < arr.size(); i++) {
            diff.add(arr.get(i) - arr.get(i - 1));
        }
        return diff;
    }

    public static void applyDifference(List<Integer> arr, int l, int r, int c) {
        arr.set(l, arr.get(l) + c);
        if (r + 1 < arr.size()) {
            arr.set(r + 1, arr.get(r + 1) - c);
        }
    }
}
二维差分
import java.util.ArrayList;
import java.util.List;

public class Difference2D {
    public static List<List<Integer>> getDifference(List<List<Integer>> matrix) {
        int rows = matrix.size();
        int cols = matrix.get(0).size();
        List<List<Integer>> diff = new ArrayList<>();
        for (int i = 0; i < rows; i++) {
            List<Integer> row = new ArrayList<>();
            row.add(matrix.get(i).get(0));
            for (int j = 1; j < cols; j++) {
                row.add(matrix.get(i).get(j) - matrix.get(i).get(j - 1));
            }
            diff.add(row);
        }
        return diff;
    }

    public static void applyDifference(List<List<Integer>> diff, int x1, int y1, int x2, int y2, int c) {
        diff.get(x1).set(y1, diff.get(x1).get(y1) + c);
        diff.get(x1).set(y2 + 1, diff.get(x1).get(y2 + 1) - c);
        diff.get(x2 + 1).set(y1, diff.get(x2 + 1).get(y1) - c);
        diff.get(x2 + 1).set(y2 + 1, diff.get(x2 + 1).get(y2 + 1) + c);
    }
}
位运算
public class BitOperations {
    public static int getKthBit(int n, int k) {
        return (n >> k) & 1;
    }

    public static int lowbit(int n) {
        return n & -n;
    }
}
双指针算法
import java.util.ArrayList;
import java.util.List;

public class TwoPointers {
    public static List<Integer> twoSum(List<Integer> nums, int target) {
        int i = 0, j = nums.size() - 1;
        while (i < j) {
            int sum = nums.get(i) + nums.get(j);
            if (sum < target) {
                i++;
            } else if (sum > target) {
                j--;
            } else {
                return List.of(i, j);
            }
        }
        return List.of();
    }
}
离散化
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Discretization {
    public static List<Integer> discretize(List<Integer> arr) {
        List<Integer> sortedArr = new ArrayList<>(arr);
        Collections.sort(sortedArr);
        sortedArr = new ArrayList<>(sortedArr.stream().distinct().toList());

        List<Integer> res = new ArrayList<>();
        for (int num : arr) {
            int idx = Collections.binarySearch(sortedArr, num);
            res.add(idx + 1);
        }
        return res;
    }
}
区间合并
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class IntervalMerge {
    public static List<int[]> merge(List<int[]> intervals) {
        List<int[]> res = new ArrayList<>();
        if (intervals.isEmpty()) {
            return res;
        }

        intervals.sort(Comparator.comparingInt(a -> a[0]));

        int start = intervals.get(0)[0];
        int end = intervals.get(0)[1];

        for (int i = 1; i < intervals.size(); i++) {
            int[] interval = intervals.get(i);
            if (end < interval[0]) {
                res.add(new int[]{start, end});
                start = interval[0];
                end = interval[1];
            } else {
                end = Math.max(end, interval[1]);
            }
        }
        res.add(new int[]{start, end});

        return res;
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到