求第二小元素算法

求第二小元素的时间复杂度是Θ(n),使用暴力求解和该算法的时间复杂度都是Θ(n),该算法只是把最坏情况比较次数从 2 n − 3 2n-3 2n3次降低到 n + ⌈ l g n ⌉ − 2 n+\lceil lgn\rceil-2 n+lgn2

暴力求解

取两个数作为最小元素和第二小元素,然后依次取剩下的元素和现有的最小元素、第二小元素作比较,最后获得所有元素中的最小元素和第二小元素。

理想情况比较 n − 1 n-1 n1次,最坏情况比较 2 n − 3 2n-3 2n3次。

优化算法

该算法的核心思想是:第二小元素只可能被最小元素“干掉”,所以我们只需要找出所有和最小元素比较过的元素,从中找最小元素即是所有元素的第二小元素。

那么如何减少和最小元素比较过的元素个数呢(目标是最坏情况下尽可能少)?可以想到使用二叉树。

如下图,建立一棵有 n n n个叶子节点的完全二叉树,每个元素作为一个叶子节点,从下向上两两比较,最后根节点就是最小元素。

然后退回去找出所有和最小元素比较过的元素(蓝色圆圈的元素),从这些元素中逐个比较找其中的最小元素即可。
mg-rjCve6Ew-1587392822801

算法实现

完全二叉树的方法是可以直接实现的,只要每个非叶子节点同时保留 以自己为根的子树的最小元素 和 被“干掉”的元素是左孩子还是右孩子 即可实现所说算法。

但是使用完全二叉树过于浪费空间了,为了优化算法,我们使用链表的方式来实现。

链表方式的实现:

每个元素都有一个链用来保留和自己比较过的元素(以下将该链称为“击杀名单”)。

两两分组进行比较,比较后,失败者(较大元素)清空自己的击杀名单,然后把自己放入胜利者(较小元素)的击杀名单中。

重复上一步直到只剩一个胜利者(最小值)。

扫描一次最终胜利者的“击杀名单”,找到其中的最小值,即为所有元素的第二小元素。

当然,为了用链表实现,所有未被击杀的元素也要形成一个链。

举例:

如下图,H为头结点,共有7个元素,红圈表示进行比较,黄色区域表示“未被击杀元素”,黄色区域以外是“击杀名单”。

在这里插入图片描述

总结

其实该算法的使用价值不大,因为对时间优化不大,反而需要开辟不少存储空间保存指针。但是我认为该算法很有意思,所以就整理了出来。

参考资料:

https://blog.csdn.net/mishifangxiangdefeng/article/details/7983809
https://www.zhihu.com/question/33113457

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值