| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 求整数最大间隔-性能(hash算法) -> 正文阅读 |
|
[数据结构与算法]求整数最大间隔-性能(hash算法) |
题目描述 Output Format
?作为刚学数据结构的小白,刚看题时其实还是有点懵的。老师上课讲的散列(哈希)还没有完全搞明白,结果当天晚上12点前就要提交这道题,内心小崩~~~~主要当天课太多,很晚才回宿舍,我自知我能力有限,单靠自己想肯定是完不成了,所以就在CSDN上搜索了一下题目,虽然有的博主发过,但并没有太多讲解就直接上了代码。其实那时候挺崩溃的,虽然很不甘哈,但还是直接Ctrl+C、Ctrl+V了〔╯o╰〕。转天我研究了一下才决定写一写关于这道题的一些想法,既为了自己看着方便也为了以后有的同学理解。 (PS:说明一下,我理解这道题时既依靠了老师的提示,也依靠了网上博主的代码,源代码链接我放在下面。对于源代码我其实有一些意见不同的地方,所以我的代码和原作者的有些出入。也许是我理解不到位哈,如果大家有想法,欢迎在下面留言哦!但也请兄弟姐妹们不要太暴躁哈,毕竟关爱小白人人有责呀(>▽<)!!) 链接:https://blog.csdn.net/weixin_45964488/article/details/111604028 一、明确题目要求说实话,一开始我并没有理解到底说的是什么意思。有的同学调侃:“题目说了要干什么,但又没完全说。”其实题目的意思是给定一个大小为n的数组(外部输入),将这n个数标在实轴上,问:分为的n-1段有界区间(另加两段无界的,那个就不用算啦)其中,哪一段最长。(如下图)
换句话说就是问将数组的n个元素排完序后,前一个数和后一个数的差(共n-1个)最大是多少。? 二、如何实现知道了题目的要求,现在我们需要确定做什么。 需要做的就是排序和比较。 一般来讲我们首先想到的是先通过排序算法将数组排好序,之后再去通过循环去比较每个相邻数的差的大小,是个可行的办法。不过,我们要看一下题目中的一句话:
现在,反观我们所有的八大排序算法,插排、快排、冒泡排、堆排等等,时间复杂度都不会低于O(nlogn),所以我们需要寻找另一条路径。 这时候hash就登上了“历史舞台”。具体的哈希表(散列表)的概念及相关大家可以去自行搜索,这里就不赘述了。 运用hash算法我们可以将时间复杂度控制在O(n)层级上,可以说是性能极高的算法。不知道大家在看到一个比常规方法性能高得多的算法时是什么想法,我是感到震惊,同时又感到自己就是个大大的 fw (≧ ﹏ ≦) 咳咳,言归正传。具体是算法流程是这样:
其实整个核心流程就是要找到合适的散列函数,将大小相近的数分到相同的桶中(桶本质上就是数组,用来容纳大小相近的数),经过每个桶内数与桶间数的距离比较最后确定出最大的距离,即maxgap。 三、代码实现现在我们就来逐步看一下代码的操作 首先说一点,题目中给出的随机数函数就是用来随机填充数组的,不用多想直接用就可以。 另外,上述功能的实现全部放在了一个函数里
?传入的是?main()?函数中用随机数函数生成的随机数数组。 1、找到数组中的最大、最小值
amax表示a数组中的最大值,amin大家也能猜到,用来表示数组中的最小值。 最后的 if 语句大家需要注意一下,如果整个数组的最大最小值是一样的,那么就可以直接下班退出啦,不过可以直接下班的好事还是少呀,唉 ∩﹏∩ 有的同学会问这一步有什么用,真的是好问题,所以好问题得在后面说,嘿嘿 2、将有效范围均匀地划分为n-1段(n桶)//相当于散列表
bucket[] 只是用来表示该桶是否为空,虽然后面我们要记录每个桶中的最大最小值,但是只要动态记录就可以了,并用不到静态储存,具体的后面会讲,所以这里将其设置成布尔数组就可以啦。 ( PS:我参考的那个博主申请的数组大小是 n+1。但我认为即使是最极端的情况下,n个数也只是会被分入 n 个桶,所以申请 n 就可以了,并用不到 n+1。) 3、?通过散列,将各点归入对应的桶 ;在各桶中动态记录最大、最小值(原3、4步合并)
imax[] 用于记录每个桶中的最大值,imin[]?则用于记录每个桶中的最小值 ,index表示将每个数归入的桶的下标。 我觉得这一段代码的关键是 gap 的计算与 index 的确定。当时我的疑问就是为什么要这么算。现在我来尝试解释一下。 首先,我们要将数组中的每个数归入桶中,而桶其实就是前面的 bucket[],我们在申请数组时的下标只能是连续的从 0 到 n-1 ,而不可能是跳跃的下标。所以要想办法通过操作将每个数通过计算分入不同的桶,而且算出的下标(index)不能大于n-1。gap的计算方法大家可以看到,它实际上就是一个标尺,通过计算每个数与最小值的差与gap的倍数来确定进入哪个桶。最小的情况是 a[i] 等于amin,结果 index 为 0;最大情况是 a[i] 等于amax,结果index为 n-1,正好符合需求。【其实我认为这种处理方式大家可以记住,下此遇到类似的排序情况就可以直接使用了】 后面的代码大家基本上就可以看明白。就是动态存储了每个桶中的最大最小值,以及将非空的桶置为1。以上的过程就相当于进行了数据排序,只不过时间性能有了提升!强调一点就是注意gap是double 类型,因为是标尺还是越精确越好,而后面的index需要是整型,因为下标只能是整数。 ( PS:原博主申请的记录各桶最大最小值的数组大小都是n+1,但我觉的n就足够了,理由同上) ?4、算出相邻(非空)桶之间的“距离”?
?lastmax用于表示前一个桶的最大值。 声明maxgap用于存储最终结果,虽然代码里写的是初值为1,但我认为更应该设置为INT_MIN(即最小的整型数字),因为我们也不确定是否有负数。但是设为0可以通过并且学校OJ并不识别INT_MIN,所以我这里就继续使用0了。 第一个for循环用于找到第一个非空桶,并将其中的最大值赋给lastmax。 第二个for循环就是要比较找出最大的差值,比较的三者是现在所处桶的最小值与前一桶的最大值的差、现在所处桶的最大值与最小值的差、以及maxgap本身。 (PS:原博主在第二个循环中的比较是下面那样的。但我认为所处桶内的最大最小的差不能被忽视,即使它们之间的距离可能较短,但还是必须要考虑的一点)
好啦,以上就是这道题的全部内容啦。这是我第一次写文章,总归有不足,不管是排版还是思路,亦或者能力上的缺陷也请各位同学们指出哈。凡事都是有第一次,第一次写不好,第二次一定会有进步。蟹蟹大家啦!!!!!!!!哦,差点忘了完整代码~~~
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 9:36:28- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |