• 华为OD机试 - 多段线数据压缩(Java 2024 D卷 100分)


    在这里插入图片描述

    华为OD机试 2024D卷题库疯狂收录中,刷题点这里

    专栏导读

    本专栏收录于《华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)》

    刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

    一、题目描述

    下图中,每个方块代表一个像素,每个像素用其行号和列号表示。

    在这里插入图片描述

    为简化处理,多段线的走向只能是水平、竖直、斜向45度。

    上图中的多段线可以用下面的坐标串表示:(2,8),(3,7),(3,6),(3,5),(4,4),(5,3),(6,2),(7,3),(8,4),(7,5)。

    但可以发现,这种表示不是最简的,其实只需要存储6个蓝色的关键点即可,它们是线段的起点、拐点、终点,而剩下4个点是冗余的。

    现在,请根据输入的包含有几余数据的多段线坐标列表,输出其最化的结果。

    二、输入描述

    形如2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5

    1、所有数字以空格分隔,每两个数字一组,第一个数字是行号,第二个数字是列号;

    2、行号和列号范围为[0,64),用例输入保证不会越界,考生不必检查;

    3、输入数据至少包含两个坐标点

    三、输出描述

    形如2 8 3 7 3 5 6 2 8 4 7 5

    压缩后的最简化坐标列表,和输入数据的格式相同。

    补充说明

    输出的坐标相对顺序不能变化。

    四、解题思路

    这个问题的核心是找到路径中的关键点,关键点定义为路径中方向发生变化的点。为了找到这些关键点,我们需要遍历路径中的所有点,计算每个点相对于前一个点的方向,并检查是否发生了方向变化。如果发生了方向变化,则记录当前点为关键点。

    具体解题步骤如下:

    1. 初始化变量:
      • 读取输入的坐标数组。
      • 初始化上一个点的坐标 prevX 和 prevY。
      • 初始化上一次的运动方向 prevDirX 和 prevDirY。
    2. 遍历坐标数组:
      • 以步长为2遍历坐标数组,因为每两个元素表示一个点的坐标。
      • 获取当前点的坐标 currX 和 currY。
      • 计算当前点相对于上一个点的偏移量 deltaX 和 deltaY。
      • 计算当前的运动方向 currDirX 和 currDirY,方向的计算是基于偏移量的符号,表示移动的方向(-1、0、1)。
      • 比较当前的运动方向和上一次的运动方向,如果发生了变化,则记录上一个点为关键点。
    3. 记录结果:
      • 最后一个点也是关键点,需要记录下来。
      • 返回所有关键点的字符串表示。

    五、Java算法源码

    public class Test01 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            // 读取并解析输入的坐标数组
            int[] coordinates = Arrays.stream(scanner.nextLine().split(" "))
                    .mapToInt(Integer::parseInt).toArray();
            // 输出路径中的关键点
            System.out.println(findKeyPoints(coordinates));
        }
    
        /**
         * 找出路径中的关键点并返回结果
         * @param coordinates 路径的坐标数组
         * @return 关键点的字符串表示
         */
        public static String findKeyPoints(int[] coordinates) {
            StringJoiner result = new StringJoiner(" ");
    
            // 初始化上一个点的坐标
            int prevX = coordinates[0];
            int prevY = coordinates[1];
            // 初始化上一次运动方向
            int prevDirX = 0;
            int prevDirY = 0;
    
            // 遍历坐标数组,步长为2,因为每两个元素表示一个点的坐标
            for (int i = 2; i < coordinates.length; i += 2) {
                int currX = coordinates[i];
                int currY = coordinates[i + 1];
    
                // 计算当前点相对于上一个点的偏移量
                int deltaX = currX - prevX;
                int deltaY = currY - prevY;
    
                // 计算本次运动方向
                int maxDelta = Math.max(Math.abs(deltaX), Math.abs(deltaY));
                int currDirX = deltaX / maxDelta;
                int currDirY = deltaY / maxDelta;
    
                // 如果两次运动的方向不同,则上一个点是拐点,记录下来
                if (currDirX != prevDirX || currDirY != prevDirY) {
                    result.add(prevX + " " + prevY);
                }
    
                // 更新上一个点的坐标和方向
                prevX = currX;
                prevY = currY;
                prevDirX = currDirX;
                prevDirY = currDirY;
            }
    
            // 最后一个点也是关键点,记录下来
            result.add(prevX + " " + prevY);
    
            return result.toString();
        }
    }
    

    六、效果展示

    1、输入

    2 8 3 7 3 6 3 5 4 4 5 3 6 2 7 3 8 4 7 5

    2、输出

    2 8 3 7 3 5 6 2 8 4 7 5

    3、说明

    如上图所示,6个蓝色像素的坐标依次是(2,8)、(3,7)、(3,5)、(6,2)、(8,4)、(7,5)。

    将他们按顺序出即可。

    在这里插入图片描述


    🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 C卷 200分)

    🏆本文收录于,华为OD机试(JAVA)真题(D卷+C卷+A卷+B卷)

    刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

    在这里插入图片描述

  • 相关阅读:
    CSS 实现祥云纹理背景
    Arduino 学习笔记_3 案例:按下按钮生成一位随机数字,在数码管中显示
    java毕业设计春之梦理发店管理Mybatis+系统+数据库+调试部署
    springMVC中统一异常处理@ControllerAdvice
    Linux与Shell学习--shell系列9--流程控制2(for循环)
    【go语言之timer实现】
    GO学习笔记(3)
    理解Go中的布尔逻辑
    Beautiful Soup抓取AJAX动态网站的注意事项
    JVM内存模型及分区
  • 原文地址:https://blog.csdn.net/guorui_java/article/details/139705798