华为OD刷题C卷 - 每日刷题 14(可以组成网络的服务器、用连续自然数之和来表达整数)

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

1、(可以组成网络的服务器):

这段代码是解决“可以组成网络的服务器”的问题。它提供了一个Java类Main,其中包含main方法和getResult方法,以及一个辅助方法bfs,用于统计机房中最大的局域网包含的服务器个数。

main方法首先读取二维数组的行数n和列数m,然后读取服务器信息矩阵matrix。接着,调用getResult方法并打印结果。

getResult方法遍历服务器信息矩阵,对于每个服务器(用1表示),使用bfs方法进行广度优先搜索,以找到最大的局域网。bfs方法使用一个队列path来存储待检查的服务器坐标,并通过邻接节点的检查来扩展局域网。每找到一个新服务器,就将其添加到队列中,并将其状态标记为已访问(用0表示)。当队列为空时,表示已经找到了从当前服务器出发的最大局域网。

最后,getResult方法返回最大的局域网大小。

2、(用连续自然数之和来表达整数):

这段代码是解决“用连续自然数之和来表达整数”的问题。它提供了一个Java类Main,其中包含main方法和getResult方法,用于找出一个整数的所有可能的连续自然数之和的表达式,并打印每种表达式以及它们的个数。

main方法读取目标整数n,然后调用getResult方法并打印所有可能的表达式和最终的表达式个数。

getResult方法使用滑动窗口技术来找出所有可能的连续自然数序列,这些序列的和等于目标整数n。通过移动左右指针leftright,代码可以找到所有可能的连续序列,并记录它们的起始索引和结束索引。找到所有序列后,使用StringJoiner来构建每个序列的表达式字符串,并按序列长度升序排列。

最后,getResult方法返回一个包含所有表达式和最终表达式个数的列表。

package OD233;

import java.util.LinkedList;
import java.util.Scanner;

/**
 * @description 可以组成网络的服务器
 * @level 6
 * @score 200
 * @url https://hydro.ac/d/HWOD2023/p/OD233
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    static int[][] offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    private static int n;
    private static int m;
    private static int[][] matrix;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //n行 m列
        n = sc.nextInt();
        m = sc.nextInt();

        //服务器矩阵
        matrix = new int[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                matrix[i][j] = sc.nextInt();
            }
        }

        //输出最大局域网的服务器个数
        System.out.println(getResult());
    }

    public static int getResult() {
        //记录题解,不断更新较大值
        int ans = 0;
        //遍历,从每一个起点扩散
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                //如果是1,则进行bfs递归,找到该点最多能扩散的局域网服务器个数
                if (matrix[i][j] == 1) {
                    ans = Math.max(ans, bfs(i, j));
                }
            }
        }

        return ans;
    }


    /**
     * 从matrix[i][j]为中心,扩散寻找最多的局域网服务器
     * 类似LeetCode200题,岛屿数量 : https://leetcode.cn/problems/number-of-islands/description/
     *
     * @param i
     * @param j
     * @return int
     * @create 2024/4/3 17:13
     */
    public static int bfs(int i, int j) {
        //储存找到服务器的坐标
        LinkedList<int[]> path = new LinkedList<>();
        //初始matrix[i][j]=1,所以初始count=1
        matrix[i][j] = 0;
        int count = 1;

        //添加起点
        path.add(new int[]{i, j});

        while (path.size() > 0) {
            int[] pos = path.removeFirst();
            int x = pos[0];
            int y = pos[1];

            //向四周位移扩散
            for (int[] offset : offsets) {
                int newX = x + offset[0];
                int newY = y + offset[1];
                //如果没有越界且是服务器
                if (newX >= 0 && newX < n && newY >= 0 && newY < m && matrix[newX][newY] == 1) {
                    //找到的服务器+1
                    count++;
                    //添加到坐标集合
                    path.add(new int[]{newX, newY});
                    //把该点设为1,防止回头
                    matrix[newX][newY] = 0;
                }
            }
        }
        //返回最大局域网服务器个数
        return count;
    }


}
package OD241;

import java.util.*;

/**
 * @description 用连续自然数之和来表达整数
 * @level 5
 * @score 100
 */

/**
 * 题目描述
 * 一个整数可以由连续的自然数之和来表示。
 * <p>
 * 给定一个整数,计算该整数有几种连续自然数之和的表达式,且打印出每种表达式
 * <p>
 * 输入描述
 * 一个目标整数T (1 <=T<= 1000)
 * <p>
 * 输出描述
 * 该整数的所有表达式和表达式的个数。
 * <p>
 * 如果有多种表达式,输出要求为:自然数个数最少的表达式优先输出,每个表达式中按自然数递增的顺序输出,具体的格式参见样例。
 * <p>
 * 在每个测试数据结束时,输出一行”Result:X”,其中X是最终的表达式个数。
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        //存放结果
        ArrayList<String> result = getResult(n);
        result.forEach(System.out::println);
    }

    public static ArrayList<String> getResult(int t) {
        //存放结果
        ArrayList<String> result = new ArrayList<>();
        //创建一个从1-n的数组,使用滑动窗口
        int[] arr = new int[t];
        for (int i = 0; i < t; i++) {
            arr[i] = i + 1;
        }
        int left = 0;
        int right = 1;
        //初始化和
        int sum = arr[left];
        //存放步骤和
        ArrayList<int[]> ans = new ArrayList<>();
        //当左指针到达数组末尾,结束循环
        while (left < t) {
            //如果小于n,则左指针移动
            if (sum > t) {
                sum -= arr[left++];
            } else if (sum == t) {
                //记录此时的数组元素 包括left 不包含right
                ans.add(Arrays.copyOfRange(arr, left, right));
                //窗口往右移动
                sum -= arr[left++];
                //此时right有可能已经到达数组末尾
                if (right >= t) {
                    break;
                }
                //没有到达边界则往右移动
                sum += arr[right++];

            } else {
                //sum<n 右指针往右移动
                sum += arr[right++];

            }
        }
        //排序 按长度升序
        ans.sort(Comparator.comparing(a -> a.length));
        ans.forEach(a -> {
            StringJoiner sj = new StringJoiner("+", t + "=", "");//前缀是n= 连接符是+ 后置是""
            Arrays.stream(a).forEach(i -> sj.add(i + ""));
            result.add(sj.toString());
        });

        result.add("Result:" + ans.size());
        return result;
    }
}
  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值