Java--ACM常用语句
·
Java–ACM常用语句
一、输入输出处理
1、快速输入(替代Scanner,处理大量数据)
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] parts = br.readLine().split(" "); // 读取一行并分割
int n = Integer.parseInt(parts[0]);
// 读取多组数据(按行读取)
String line;
while ((line = br.readLine()) != null) {
if (line.isEmpty()) continue; // 跳过空行
int x = Integer.parseInt(line);
// 处理逻辑
}
}
}
2、快速输出(避免System.out.println频繁调用)
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("Hello\n"); // 写入字符串,手动加换行
bw.write(String.valueOf(123) + "\n"); // 写入数字
bw.flush(); // 必须刷新,否则可能不输出
}
}
3、格式化输出(String.format)
// 保留2位小数
double pi = 3.14159;
System.out.println(String.format("%.2f", pi)); // 输出 3.14
// 整数补零(共3位)
int num = 5;
System.out.println(String.format("%03d", num)); // 输出 005
二、常用数据结构
1、数组(Array)与动态数组(ArrayList)
// 数组初始化
int[] arr = new int[10]; // 长度10的int数组
int[] arr2 = {1, 2, 3}; // 直接赋值
// ArrayList(动态扩容,替代数组)
import java.util.ArrayList;
ArrayList<Integer> list = new ArrayList<>();
list.add(1); // 添加元素
list.get(0); // 获取索引0的元素
list.remove(0); // 删除索引0的元素
list.size(); // 长度
2、哈希表(HashMap)与哈希集(HashSet)
import java.util.HashMap;
import java.util.HashSet;
// HashMap:键值对计数
HashMap<Integer, Integer> cnt = new HashMap<>();
cnt.put(5, cnt.getOrDefault(5, 0) + 1); // 计数(不存在则默认0)
int val = cnt.getOrDefault(3, 0); // 获取值,默认0
// HashSet:去重、判断存在
HashSet<Integer> set = new HashSet<>();
set.add(1);
set.contains(1); // 返回true
set.remove(1);
3、队列(Queue)与双端队列(Deque)
import java.util.LinkedList;
import java.util.Queue;
import java.util.Deque;
// 队列(FIFO,适合BFS)
Queue<Integer> queue = new LinkedList<>();
queue.offer(1); // 入队
queue.poll(); // 出队(队首)
queue.peek(); // 查看队首
// 双端队列(Deque,支持首尾操作)
Deque<Integer> deque = new LinkedList<>();
deque.addFirst(0); // 队首入队
deque.addLast(2); // 队尾入队
deque.pollFirst(); // 队首出队
deque.pollLast(); // 队尾出队
4、堆(PriorityQueue,优先队列)
import java.util.PriorityQueue;
// 小根堆(默认,队首为最小元素)
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
// 大根堆(通过比较器实现)
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
maxHeap.offer(3); // 入堆
maxHeap.poll(); // 出堆(队首最大元素)
maxHeap.peek(); // 查看堆顶
三、算法模版
1、排序与二分查找
import java.util.Arrays;
// 数组排序(升序)
int[] arr = {3, 1, 2};
Arrays.sort(arr); // 排序后:[1, 2, 3]
// 二分查找(Arrays.binarySearch,返回索引,不存在则返回负数)
int idx = Arrays.binarySearch(arr, 2); // 返回1
if (idx < 0) {
// 不存在,插入位置为 -idx - 1
}
// 自定义二分查找(找目标值)
public static int binarySearch(int[] arr, int target) {
int left = 0, right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // 避免溢出
if (arr[mid] == target) return mid;
else if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}
2、前缀和(快速求区间和)
// 一维前缀和
int n = arr.length;
int[] prefix = new int[n + 1];
for (int i = 0; i < n; i++) {
prefix[i + 1] = prefix[i] + arr[i];
}
int sumLR = prefix[r + 1] - prefix[l]; // 求arr[l..r]的和(0<=l<=r <n)
3、差分(快速区间更新)
// 一维差分:对[l..r]加val,最后求前缀和得结果
int n = 10;
int[] diff = new int[n + 2]; // 避免越界
int l = 2, r = 5, val = 3;
diff[l] += val;
diff[r + 1] -= val;
// 还原数组
int[] res = new int[n];
res[0] = diff[0];
for (int i = 1; i < n; i++) {
res[i] = res[i - 1] + diff[i];
}
4、并查集(Union-Find,处理连通性)
class UnionFind {
int[] parent;
int[] rank;
public UnionFind(int size) {
parent = new int[size];
rank = new int[size];
for (int i = 0; i < size; i++) {
parent[i] = i; // 初始化父节点为自身
rank[i] = 0;
}
}
// 路径压缩
public int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
// 按秩合并
public void union(int x, int y) {
int xRoot = find(x);
int yRoot = find(y);
if (xRoot == yRoot) return;
if (rank[xRoot] < rank[yRoot]) {
parent[xRoot] = yRoot;
} else {
parent[yRoot] = xRoot;
if (rank[xRoot] == rank[yRoot]) {
rank[xRoot]++;
}
}
}
}
5、DFS与BFS
import java.util.*;
// DFS(递归,邻接表为例)
public static void dfs(int u, List<List<Integer>> adj, boolean[] visited) {
visited[u] = true;
for (int v : adj.get(u)) {
if (!visited[v]) {
dfs(v, adj, visited);
}
}
}
// BFS(队列,邻接表为例)
public static void bfs(int start, List<List<Integer>> adj, boolean[] visited) {
Queue<Integer> queue = new LinkedList<>();
queue.offer(start);
visited[start] = true;
while (!queue.isEmpty()) {
int u = queue.poll();
for (int v : adj.get(u)) {
if (!visited[v]) {
visited[v] = true;
queue.offer(v);
}
}
}
}
四、优化技巧
1、避免超时
- 用 BufferedReader/BufferedWriter 替代 Scanner/System.out,尤其大数据量时。
- 数组比 ArrayList 快,能确定大小的场景优先用数组。
- 字符串拼接用 StringBuilder,避免 + 运算符(效率低):
StringBuilder sb = new StringBuilder();
sb.append("a").append(123).append("\n");
System.out.println(sb.toString());
2、处理多组测试用例
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
while (t-- > 0) {
// 每组测试用例逻辑
}
3、常量与静态方法
频繁使用的变量定义为 static final(如 INF = 0x3f3f3f3f),工具方法定义为 static,减少对象创建开销。
五、常见情景示例
- 统计数字出现次数:
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] parts = br.readLine().split(" ");
HashMap<String, Integer> cnt = new HashMap<>();
for (String s : parts) {
cnt.put(s, cnt.getOrDefault(s, 0) + 1);
}
// 输出结果
for (Map.Entry<String, Integer> entry : cnt.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
}
- 最长递增子序列(LIS):
import java.util.*;
public class Main {
public static int lis(int[] arr) {
List<Integer> tails = new ArrayList<>();
for (int num : arr) {
int idx = Collections.binarySearch(tails, num);
if (idx < 0) idx = -idx - 1; // 计算插入位置
if (idx == tails.size()) {
tails.add(num);
} else {
tails.set(idx, num);
}
}
return tails.size();
}
}
更多推荐



所有评论(0)