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

73 篇文章 0 订阅
37 篇文章 1 订阅

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

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作为结果。

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;
        }
    }
}
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;
        }
    }
}

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值