华为OD刷题C卷 - 每日刷题 7(字符串分隔(二)、欢乐的周末)

两段代码分别解决了两个不同的问题,下面是对它们的概述:

1、(字符串分隔(二)):

这段代码是解决"字符串分隔(二)"的问题。它提供了一个Java类Main,其中包含一个方法solution,该方法接收一个字符串s和一个整数k。任务是对字符串s进行处理,使其除第一个子串外,其余的子串每k个字符组成新的子串,并根据子串中大写字母和小写字母的数量进行大小写转换。

代码首先使用String.split方法以'-'为分隔符将原始字符串s分割成多个子串,并将这些子串加入到StringJoiner中,它用于构建最终的字符串。

接着,代码遍历除了第一个子串之外的所有子串,以k为步长进行切片,然后对每个切片后的子串调用change方法进行大小写转换。change方法会计算子串中大写字母和小写字母的数量,并根据数量的多少来决定是否进行大小写转换。

最后,返回构建好的字符串。

2、(欢乐的周末):

这段代码是解决"欢乐的周末"的问题。它提供了一个Java类Main,其中包含一个方法getResult,该方法接收一个地图的二维数组表示,地图上有通畅的道路(用0表示)、障碍物(用1表示)、小华或小为的位置(用2表示)、以及被选中的聚餐地点(用3表示)。任务是计算小华和小为都能到达的聚餐地点的数量。

代码首先读取地图的大小和具体信息,然后使用一个UnionFindSet对象来处理地图上的连通性。UnionFindSet是一个并查集的数据结构,用于快速判断两个节点是否在同一个连通分量中。

在处理地图时,代码会记录小华和小为的位置,以及所有聚餐地点的位置。然后,遍历地图上的每个单元格,如果单元格不是障碍物,则将其与相邻的非障碍物单元格合并(在并查集中的术语是"union")。

接着,代码会找到小华和小为所在连通分量的根节点,并检查这两个根节点是否相同。如果不同,则表示小华和小为无法到达同一个聚餐地点,返回0

如果小华和小为在同一个连通分量中,代码将继续遍历所有聚餐地点,并检查每个地点是否也在该连通分量中。如果在,计数器ans会增加。

最后,返回计数器ans作为结果。

java 复制代码
package OD154;

import java.util.Scanner;
import java.util.StringJoiner;

/**
 * @description 字符串分隔(二)
 * @level 6
 */

/**
 * 题目描述
 * 给定一个非空字符串S,其被N个'-'分隔成N+1的子串,给定正整数K,要求除第一个子串外,其余的子串每K个字符组成新的子串,并用'-'分隔。
 * <p>
 * 对于新组成的每一个子串,如果它含有的小写字母比大写字母多,则将这个子串的所有大写字母转换为小写字母;
 * <p>
 * 反之,如果它含有的大写字母比小写字母多,则将这个子串的所有小写字母转换为大写字母;大小写字母的数量相等时,不做转换。
 * <p>
 * 输入描述
 * 输入为两行,第一行为参数K,第二行为字符串S。
 * <p>
 * 输出描述
 * 输出转换后的字符串。
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //分隔子串的长度
        int n = Integer.parseInt(sc.nextLine());
        //原始子串
        String s = sc.nextLine();
        System.out.println(solution(s, n));
    }


    //将字符串按k长度分隔,中间添加"-",并转换大小写
    public static String solution(String s, int k) {
        String[] strs = s.split("-");
        StringBuilder sb = new StringBuilder();
        StringJoiner  sj = new StringJoiner("-");
        //第一个直接加
        sj.add(strs[0]);

        //把剩下的字符串合并成一个新字符串
        for (int i = 1; i < strs.length; i++) {
            sb.append(strs[i]);
        }
        String newStr = sb.toString();
        //把剩下的字符串按k个分组,最后一组是到末尾结束
        for (int i = 0; i < newStr.length(); i += k) {
            String sub = newStr.substring(i, Math.min(i + k, newStr.length()));
            //转换大小写后添加进sj
            sj.add(change(sub));
        }

        return sj.toString();
    }

    //将字符串根据大小写数量转换大小写
    public static String change(String s) {
        int upper = 0;
        int lower = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) >= 'A' && s.charAt(i) <= 'Z') {
                upper++;
            }else if (s.charAt(i) >= 'a' && s.charAt(i) <= 'z') {
                lower++;
            }
        }
        //如果大写多
        if (upper > lower) {
            return s.toUpperCase();
        }else if (lower > upper) {
            return s.toLowerCase();
        }else {
            return s;
        }
    }
}
java 复制代码
package OD197;

import java.util.ArrayList;
import java.util.Scanner;

/**
 * @description 欢乐的周末
 * @level 7
 * @score 100
 * @url https://hydro.ac/d/HWOD2023/p/OD197
 */

/**
 * 题目描述
 * 小华和小为是很要好的朋友,他们约定周末一起吃饭。
 * <p>
 * 通过手机交流,他们在地图上选择了多个聚餐地点(由于自然地形等原因,部分聚餐地点不可达),求小华和小为都能到达的聚餐地点有多少个?
 * <p>
 * 输入描述
 * 第一行输入m和n,m代表地图的长度,n代表地图的宽度。
 * <p>
 * 第二行开始具体输入地图信息,地图信息包含:
 * <p>
 * 0 为通畅的道路
 * <p>
 * 1 为障碍物(且仅1为障碍物)
 * <p>
 * 2 为小华或者小为,地图中必定有且仅有2个 (非障碍物)
 * <p>
 * 3 为被选中的聚餐地点(非障碍物)
 * <p>
 * 输出描述
 * 可以被两方都到达的聚餐地点数量,行末无空格。
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    //位移偏量
    static int[][] offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    private static int rows;
    private static int cols;
    private static int[][] matrix;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //长 宽
        rows = sc.nextInt();
        cols = sc.nextInt();

        //2是人位置  1是障碍物  3是聚餐地点
        matrix = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                matrix[i][j] = sc.nextInt();
            }
        }

        //输出:能共同到达的餐厅数量
        System.out.println(getResult());

    }

    public static int getResult() {
        //并查集
        UnionFindSet ufs = new UnionFindSet(rows * cols);

        //记录小华、小为的位置
        ArrayList<Integer> address = new ArrayList<>();

        //记录餐厅的位置
        ArrayList<Integer> restaurants = new ArrayList<>();

        //遍历每一个起点
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                //把除了障碍物之外的都连通
                if (matrix[i][j] != 1) {
                    //如果不是障碍物,转为一维坐标pos
                    int pos = i * cols + j;

                    //如果是小华、小为
                    if (matrix[i][j] == 2) {
                        address.add(pos);
                    } else if (matrix[i][j] == 3) {
                        restaurants.add(pos);
                    }

                    for (int[] offset : offsets) {
                        int newI = i + offset[0];
                        int newJ = j + offset[1];
                        //如果没越界,且不是障碍物
                        if (newI >= 0 && newI < rows && newJ >= 0 && newJ < cols && matrix[newI][newJ] != 1) {
                            //如果(i,j)和(newI,newJ)的位置都是非1,则合并,都转一维坐标
                            ufs.union(pos, newI * cols + newJ);
                        }
                    }
                }
            }
        }

        //小华所在连通分量的根
        int hua_fa = ufs.find(address.get(0));
        //小为
        int wei_fa = ufs.find(address.get(1));

        //如果不属于同一个分量,则无法去同一家餐厅
        if (hua_fa != wei_fa) {
            return 0;
        }

        //记录题解:共同能到达的餐厅数量
        int ans = 0;

        for (Integer restaurant : restaurants) {
            if (ufs.find(restaurant) == hua_fa) {
                ans++;
            }
        }
        return ans;
    }


}


//实现并查集
class UnionFindSet {
    int[] fa;

    public UnionFindSet(int n) {
        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[y_fa] = x_fa;
        }
    }
}
相关推荐
救救孩子把14 分钟前
深入理解 Java 对象的内存布局
java
落落落sss17 分钟前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
万物皆字节22 分钟前
maven指定模块快速打包idea插件Quick Maven Package
java
夜雨翦春韭29 分钟前
【代码随想录Day30】贪心算法Part04
java·数据结构·算法·leetcode·贪心算法
简单.is.good34 分钟前
【测试】接口测试与接口自动化
开发语言·python
我行我素,向往自由36 分钟前
速成java记录(上)
java·速成
一直学习永不止步41 分钟前
LeetCode题练习与总结:H 指数--274
java·数据结构·算法·leetcode·数组·排序·计数排序
邵泽明42 分钟前
面试知识储备-多线程
java·面试·职场和发展
Yvemil71 小时前
MQ 架构设计原理与消息中间件详解(二)
开发语言·后端·ruby
程序员是干活的1 小时前
私家车开车回家过节会发生什么事情
java·开发语言·软件构建·1024程序员节