1、(图像物体的边界):
这段代码是解决“图像物体的边界”的问题。它提供了一个Java类Main
,其中包含main
方法和getResult
方法,以及一个内部UnionFindSet
类,用于计算像素1代表的物体的边界个数。
main
方法首先读取二维数组的行数m
和列数n
,然后读取二维数组matrix
中的像素值。接着,调用getResult
方法并打印结果。
getResult
方法首先找出所有与像素5相邻的像素1的格子,并将它们作为边界存储在ArrayList
中。然后,使用并查集UnionFindSet
来合并相邻的边界。并查集通过比较边界像素之间的距离来确定它们是否相邻,从而将属于同一个边界的像素合并到同一个集合中。
最后,UnionFindSet
中的count
变量存储了最终的边界数量,并作为结果返回。
2、(英文输入法):
这段代码是解决“英文输入法”的问题。它提供了一个Java类Main
,其中包含main
方法和match
方法,用于实现英文输入法的单词联想功能。
main
方法首先读取一段由英文单词和标点符号组成的语句s
,然后读取一个英文单词前缀pre
。接着,调用match
方法并打印匹配到的单词序列。
match
方法使用正则表达式将输入语句s
分割成单词数组。然后,遍历单词数组,使用TreeSet
来存储所有以pre
为前缀的单词。TreeSet
自动对单词进行排序并避免重复。如果TreeSet
为空,则返回前缀pre
;否则,使用StringJoiner
将排序后的单词序列拼接成字符串并返回。
package OD231;import java.util.ArrayList;
import java.util.Scanner;/*** @description 图像物体的边界* @level 7* @score 200* @url https://hydro.ac/d/HWOD2023/p/OD231*/
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {private static int m;private static int n;private static int[][] matrix;//坐标偏移private static int[][] offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};public static void main(String[] args) {Scanner sc = new Scanner(System.in);m = sc.nextInt();n = sc.nextInt();matrix = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {matrix[i][j] = sc.nextInt();}}//输出System.out.println(getResult());}public static int getResult() {//记录所有边界位置ArrayList<Integer[]> brand = new ArrayList<>();for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {//如果是像素5,则扩散if (matrix[i][j] == 5) {for (int[] offset : offsets) {int newI = i + offset[0];int newJ = j + offset[1];//如果新位置不越界且为像素1,则是边界if (newI >= 0 && newI < m && newJ >= 0 && newJ < n && matrix[newI][newJ] == 1) {brand.add(new Integer[]{newI, newJ});}}}}}int k = brand.size();//并查集,对所有边界位置进行合并UnionFindSet ufs = new UnionFindSet(k);for (int i = 0; i < k; i++) {int x1 = brand.get(i)[0];int y1 = brand.get(i)[1];for (int j = i + 1; j < k; j++) {int x2 = brand.get(j)[0];int y2 = brand.get(j)[1];//如果两个边界像素1的位置横向、纵向距离均小于1,则相邻,合并//即所有绕格子5的一圈格子1是一个连通集,边界归于1,如果两个5的一圈边界有相邻,则会归于一个if (Math.abs(x1 - x2) <= 1 && Math.abs(y1 - y2) <= 1) {//合并一次则边界-1ufs.union(i, j);}}}//返回边界数量return ufs.count;}}//并查集实现
class UnionFindSet {//根节点int[] fa;//边界个数int count;public UnionFindSet(int n) {this.count = n;this.fa = new int[n];//初始化根节点是自己for (int i = 0; i < n; i++) {fa[i] = i;}}public int find(int x) {if (x != this.fa[x]) {this.fa[x] = this.find(this.fa[x]);return this.fa[x];}return x;}public void union(int x, int y) {int x_fa = this.find(x);int y_fa = this.find(y);//如果两个不同根,则合并if (x_fa != y_fa) {this.fa[x_fa] = y_fa;//边界-1this.count--;}}
}
package OD232;import java.util.*;/*** @description 英文输入法* @level 6*//*** 题目描述* 主管期望你来实现英文输入法单词联想功能。* <p>* 需求如下:* <p>* 依据用户输入的单词前缀,从已输入的英文语句中联想出用户想输入的单词,按字典序输出联想到的单词序列,* 如果联想不到,请输出用户输入的单词前缀。* 注意:* <p>* 英文单词联想时,区分大小写* 缩略形式如”don’t”,判定为两个单词,”don”和”t”* 输出的单词序列,不能有重复单词,且只能是英文单词,不能有标点符号* 输入描述* 输入为两行。* <p>* 首行输入一段由英文单词word和标点符号组成的语句str;* <p>* 接下来一行为一个英文单词前缀pre。* <p>* 0 < word.length() <= 20* 0 < str.length <= 10000* 0 < pre <= 20* 输出描述* 输出符合要求的单词序列或单词前缀,存在多个时,单词之间以单个空格分割*/
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);//读取输入String s = sc.nextLine();//前缀匹配String pre = sc.nextLine();System.out.println(match(pre, s));}//根据前缀匹配单词public static String match(String pre, String str) {//把单词用非字母分隔开String[] words = str.split("[^a-zA-Z]");//存放前缀匹配成功的单词 防重复,TreeSet自动升序TreeSet<String> list = new TreeSet<>();for (String word : words) {if (word.startsWith(pre)) {list.add(word);}}if (list.isEmpty()) {return pre;} else {StringJoiner result = new StringJoiner(" ");//按字典排序list.forEach(result::add);return result.toString();}}
}