【算法】【算法杂谈】将路径数组变为统计数组(单数组的调整与转换)

news2025/2/26 13:09:29

目录

  • 前言
  • 问题介绍
  • 解决方案
  • 代码编写
    • java语言版本
    • c语言版本
    • c++语言版本
  • 思考感悟
  • 写在最后

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
给定一个数组arr,其中该arr[i] = j表示区域i直接连接的区域是区域j,如下图所示:
在这里插入图片描述

其中arr[3] = 1,arr[6] = 1,arr[2] = 1,其中arr[1] = 0代表 1是首都
现在要求:
1、不使用新数组
2、时间复杂度在O(n)
3、将arr[i] = j代表的意义转换成 到1的距离为i的节点数有几个,如上图 arr[1] = 3
已知:路径图不会成环并且都最终通往首都

解决方案

原问题
1、不是用新数组,那么就只能使用arr这个入参提供的空间
2、时间复杂度控制在O(n)也就是只能最多使用一层循环,避免循环嵌套
3、解决该问题:arr需要经历2个周期转换,第一个周期转换为:将arr[i] = j 代表 i指向j 转换为 arr[i] = j 代表 i到首都的距离为j
第二个周期转换为: arr[i] = j 代表 i到首都的距离为j 转换为 arr[i] = j 代表 到首都的距离为i的节点数有几个

其中 转换周期1的方法:
从arr[0]开始遍历,取出arr[0],代表下一个节点j,arr[0]是起点,所以先让arr[0]为0,之后看arr[j],将arr[j]的下一个节点暂存后,再将arr[j]设置为0,代表j节点的上一个节点是节点0,如此往复一定会查到首都节点,此时将首都设置为0,开始往回走,每回去一个节点该节点的数值更新为上一个节点-1,直到回到起点为止。形象一点如下:
去过程:原2节点现在指向节点0,当遇到节点1时发现1是首都,次时往回走,看回过程
在这里插入图片描述
回过程:当从1回到2的时候,arr[1]为0,所以arr[2] = arr[1] - 1,最终这条路径变成负数路径
在这里插入图片描述
转换周期二:距离数组转统计数组
到这里arr = [-2, 0, -1, -1, -2, -2, -1]
现在开始转换成统计数组,首先不能使用多余的空间,所以我们还是需要在该数组上做转换
arr[0] = -2 说明0节点到首都的距离为2,此时判断arr[2] 是否大于0,如果小于0,说明当前位置并没有被统计过,所以暂存,改为0,然后+1。如果大于0 ,说明已经统计过,此时直接+1即可,被统计过的arr[0]此时已经统计过,但是暂时没有人距离为0(首都没遍历到),所以arr[0]变为0
一轮交换转换之后统计数组即可出现。

代码编写

java语言版本

原问题:

    /**
     * 二轮测试:从arr[i] = j 代表数值i的结点指向j含义转化为 arr[i]代表到首都的距离为i的结点数量
     * 时间复杂度O(N),空间复杂度O(1)
     * @param arr
     * @return
     */
    public static int[] path2NumsCp1(int[] arr) {
        if (arr == null) {
            return null;
        }else if (arr.length == 0) {
            return new int[]{0};
        }
        // 在原arr的基础上直接计算每一个点到首都的距离
        int cap = convertPath2Length(arr);
        arr = convertLength2Nums(arr, cap);
        return arr;
    }



    /**
     * 将代表path的arr转换成距离首都的距离(用负数表达)
     * @param arr
     */
    private static int convertPath2Length(int[] arr) {
        // 记录一下首都的index
        int capIndex = -1;
        for (int i = 0; i < arr.length; i++) {
            // 首先判断i是否已经计算过
            if (arr[i] < 0 || i == capIndex) {
                continue;
            }
            // 记录一下起点,标记起点为-1
            int cur = i;
            // next代表下一跳
            int next = arr[cur];
            arr[cur] = -1;
            while (arr[next] >= 0 && next != capIndex) {
                // 先判断是否是首都
                if (arr[next] == next) {
                    // 首都直接返回,并且首都到首都的距离是0
                    arr[next] = 0;
                    capIndex = next;
                    break;
                }
                // 需要跳跃
                int temValue = arr[next];
                // 记录回去的路
                arr[next] = cur;
                cur = next;
                next = temValue;
            }
            // 到这里next可能代表首都,也可能arr[next]已经计算过,cur代表着上一个节点的index
            // 所以从这里开始往回更新距离了
            while (arr[cur] != -1) {
                // 暂存一下下一个的位置
                int tem = arr[cur];
                // 上一个距离-1
                arr[cur] = arr[next] - 1;
                // 更新游标
                next = cur;
                cur = tem;
            }
            // 最后再更新一下arr[cur]
            arr[cur] = arr[next] - 1;
        }
        return capIndex;
    }


    /**
     * 从长度到统计数组的转换
     * @param arr
     * @return
     */
    private static int[] convertLength2Nums(int[] arr, int cap) {
        for (int i = 0; i < arr.length; i ++) {
            if (arr[i] >= 0 && i != cap) {
                // 大于0的说明统计过了
                continue;
            }
            // 到这里的都要进行统计
            // 首先拿出来arr[i],取相反数才是真的len
            int cur = arr[i];
            arr[i] = 0;
            boolean flag = false;
            while (cur <= 0) {
                // 当前位置距离首都的距离
                int len = -cur;

                if (arr[len] >= 0) {
                    arr[len] ++;
                    flag = true;
                    break;
                }else {
                    // 说明了需要循环替换
                    int next = arr[len];
                    // 替换
                    arr[len] = 0;
                    arr[len] ++;
                    // 下一个游标
                    cur = next;
                }
            }
            if (!flag) {
                arr[cur] ++;
            }
        }
        return arr;
    }


    public static void main(String[] args) {
        CommonUtils.printArr(path2NumsCp1(new int[]{9,1,4,9,0,4,8,9,0,1}));
    }

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

这道题很考验大脑的寄存器,,,
首先记录数组的变化非常绕,不让使用多余空间时,就要在一个数组上面进行交换和更新,其中需要注意的两个点:
1、用负数处理非常巧妙的将数组当做两个数组来用
2、0这个位置和0这个值非常特殊,因为其代表首都也代表距离,容易搞混,所以需要有一个变量专门标注首都以备后面判断使用。
总之需要好好体会数组的转换,并且如果限制了空间,可以使用正负数的方式将数组进行界线分割,其次,回溯的过程也很巧妙,用于路径数组变成长度数组时使用。

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/520729.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

rocketMQ的架构原理和读写逻辑

NameServer 无状态节点&#xff0c;集群部署&#xff0c;节点之间无任何信息同步&#xff0c;支持横向拓展&#xff1b; producer & consumer也是无状态的&#xff0c;每一个producer之间 &#xff0c;每一个consumer之间都不会通信&#xff0c; 每个producer和consumer内部…

STL-set容器

set/multiset容器基本概念 所有元素都会根据元素的键值自动被排序。 set/multiset属于关联式容器&#xff0c;底层结构是用二叉树实现。 set容器特点 set的元素不像map那样可以同时拥有实值和键值&#xff0c;set的元素即是键值又是实值。 set不允许两个元素有相同的键值。…

博客系统后端设计(四) - 实现获取博客详情页功能

文章目录 实现获取博客详情页功能约定前后端接口实现后端代码实现前端代码 实现获取博客详情页功能 在 博客列表页 点击 “查看全文” 按钮&#xff0c;就能跳转到博客详情页中。 跳转过去之后&#xff0c;在博客详情页中发起一个 ajax&#xff0c;从服务器获取到当前博客的具体…

【AI大模型】讯飞版大模型来了,现场发布四大行业应用成果

文章目录 前言SparkDesk讯飞星火认知大模型简介语言理解知识问答逻辑推理数学题解答代码理解与编写亲自体验写在最后前言 5月6日,讯飞星火认知大模型成果发布会在安徽合肥举行。科大讯飞董事长刘庆峰、研究院院长刘聪发布讯飞星火认知大模型,现场实测大模型七大核心能力,并…

和众视野加入飞桨技术伙伴计划,共同推动纺织行业智能化转型

近日&#xff0c;北京和众视野科技有限公司正式加入飞桨技术伙伴计划&#xff0c;双方将共同努力开发AI视觉检测技术和机器人流程自动化相结合的系统解决方案。 北京和众视野科技有限公司 北京和众视野是一家实验室检测仪器及解决方案供应商&#xff0c;一直专注于视觉检测和检…

我们在追求什么?以及我们将通往何方?记录AIGC共建者大会的一次演讲

‍‍ ​ 下一秒&#xff1a; 这个世界真如我们所见那样吗&#xff1f; 大家好&#xff0c;我是shadow。在特赞主办的AIGC创建者大会上&#xff0c;我分享了作为多重职业身份所从事的一些有意思的事情&#xff1a; 作为创作者&#xff0c;生成式人工智能展示了TA的才华&#xff…

【Fluent】XYplot中导出随着XYZ单一坐标变化的物理量规律

一、问题背景 之前我写的博客里&#xff0c;讲了如何导出区域内所有节点/单元格中心的XYZ三坐标&#xff0c;及其这个节点/单元格中心上存储的物理量信息。 但是有时候&#xff0c;我们有一个需求——只需要X、Y、Z坐标中的一个。 例如我们需要导出在某一条线上随X坐标变化的…

AICG,人工智能自动生成内容——根据文本生成图像,视频,音频

文章目录 1、什么是AICG&#xff1f;2、Text2Video3、Text2Image4、Text2Audio5、AICG的发展趋势 1、什么是AICG&#xff1f; 什么是AICG&#xff1f; AICG是指人工智能自动生成内容。通过算法模型&#xff0c;将文本转化为图像、音频、视频等多种形式。在数字时代&#xff0…

R语言 | 数据分析——统计绘图

目录 一、分类数据的图形描述 1.1 条形图barplot()函数 1.2 饼图pie()函数 二、量化数据的图形描述 2.1 点图与dotchart()函数 2.2 绘图函数plot() 2.2.1 绘制时间数列对象 ​2.2.2 向量数据与plot()函数 2.2.3 数据框数据与plot()函数 2.2.4 因子型数据与plot()函数 …

YARN 监控管理以资源管理

YARN的监控管理和资源管理 YARN WebUI V1服务JobHistoryServer服务配置 TimelineServer服务 YARN操作维护命令USER用户命令applicationjarapplicationattemptcontainerlogsqueuenodeversion Admin 管理命令resourcemanager | nodemanagerproxyserverdaemonlogrmadmintimelinese…

jenkins+springboot+gitee自动化部署项目

1、新建 maven项目我取名first 2、点击项目进行配置 3、源码管理配置 4、新建 stop.sh脚本 4、vim 编辑stop.sh脚本,build前停止jar #!/bin/bash # 获取jar包的pid pidps -ef | grep java | grep projectmonitor | awk {printf $2} if [ ! -z $pid ]; then kill -9 $pid …

Java面向对象三大特性封装和private关键字

目录 友情提醒一、Java面向对象的三大特性之封装1&#xff09;概念和好处2&#xff09;封装案例①访问权限修饰符&#xff08;private&#xff09;②构造方法与gette&setter方法③具体的封装案例 友情提醒 先看文章目录&#xff0c;大致了解知识点结构&#xff0c;直接点击…

苹果mac清理软件CleanMyMac X v4.13兼容13系统,堪称Mac最好的系统清理工具

CleanMyMac X for mac是MacOS上一款Mac清理优化工具&#xff0c;不仅包含各种清理功能&#xff0c;更是具有卸载器、维护、扩展、碎纸机这些实用功能&#xff0c;可以同时代替很多工具。它可以清理&#xff0c;优化&#xff0c;保养和监测您的电脑&#xff0c;确保您的Mac运行…

cleanmymac x 4.13新功能介绍,cleanmymac x怎么取消订阅

CleanMyMac X4.13版是一款运行在macOS系统中的专业清理软件&#xff0c;以安装方便、使用简易、功能完善等特点而闻名。CleanMyMac X在功能方面可以说是做到了极致&#xff0c;下面让我们看一下CleanMyMac X都包含有哪些功能。 CleanMyMac X是一款专业的Mac清理软件&#xff0c…

文件批量改名#批量修改文件名称中有特殊符号

在日常工作中&#xff0c;相信大家都会碰到&#xff0c;需要有修改文件名或文件夹名称等&#xff0c;修改方法也是很多种&#xff0c;如果遇到文件名有特殊符号&#xff0c;要如何把特殊符号删除或替换成自己需要的文字或其他表情符号呢。一般大家都是手动去修改&#xff0c;如…

安装和使用分布式HDFS系统在CentOS 8上进行文件上传操作

文章目录 实验目的和背景实验目的实验背景 实验过程步骤1&#xff1a;安装Java步骤2&#xff1a;下载hadoop-3.3.1.tar.gz步骤3&#xff1a;创建一个普通用户来运行Hadoop Hadoop 概念Hadoop 整体设计HDFSHDFS 的节点命名节点 (NameNode)数据节点 (DataNode)副命名节点 (Second…

语义分割学习笔记(四)膨胀卷积

推荐课程&#xff1a; 1.膨胀卷积_哔哩哔哩_bilibili&#xff08;膨胀卷积原理讲的很清楚&#xff09; 2.膨胀卷积(Dilated convolution)详解&#xff08;gradding effect问题和解决方法讲的很清楚&#xff09; 感谢博主霹雳吧啦Wz / 太阳花的小绿豆和Enzo_Mi提供视频讲解和源…

C++ OpenCV编译安装教程

文章目录 环境说明Cmake编译配置编译前配置编译选项开始正式编译安装 编写代码测试参考文章 环境说明 win10 MinGW64 Cmake 下载mingw64 (版本&#xff1a;12.1.0 posix-seh) 下载Cmake (版本3.17.5) 注&#xff1a;mingw64和cmake下载安装完成后记得把bin目录添加到【环境…

Video Grounding

一些工作能够检测包含特定动作的视频片段&#xff0c;一般称 为动作检测&#xff08;action detection&#xff09;或视频中的时序动作定位&#xff08;Temporal Action Grounding in Videos&#xff0c;TAGV&#xff09; 然而&#xff0c; TAGV 受限于预先定义的动作类别集合…

基于html+css的图展示57

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…