浅谈以数据结构的视角去解决算法问题的步骤

浅谈以数据结构的视角去解决算法问题的步骤

在程序设计中,很多复杂的算法设计问题,从数据结构的角度来看其实都可以按照这种思路来解决:

1.对于要处理的一组数据,根据实际需求整理出要处理的数据元素。

2.理清这些数据元素之间存在的逻辑关系。

3.结合以上两点,根据数据结构所学知识和实际要解决的问题,选择一种合适的数据结构。

4.数据结构包括数据的逻辑结构和数据的存储结构,同一种逻辑结构有不同的存储结构。因此要根据算法的实际需求,不仅要选择一种合适的数据逻辑结构来描述问题,更需要为其选择一种合适的存储结构。比如更新和查找操作较多,则选顺序存储结构比较合适,但如果数据的插入,删除等操作较多,则选择链式存储方法更合适。

这种方法看起来有些笨,其实很有效。遇到复杂的问题,我们可以在大脑中快速过一遍数据结构的列表,然后逐一尝试各种数据结构。这真的是一种有效的方法,因为一旦找到合适的数据结构(比如说树)。很多问题也就迎刃而解了。

下面看一个示例

问:随机生成一些数字,并保存到一个(可拓展的)数组中,假定数据元素个数为奇数个,请问如何跟踪数组的中位数?

分析问题:

1. 要处理的数据元素即一组随机数;

2. 数据元素之间为线性关系;

3. 所谓中位数即是排过序后的处于数组最中间的元素(元素为奇数个的情况下)。

4. 注:元素个数为偶数个时,中位数即中间两个数的平均值。

结题思路:

1. 将无序数组中的所有元素进行排序得到一个有序序列;

2. 找出有序序列中的最中间的那一个数即为中位数。

难点:

1. 选择哪一种数组结构来存储这些无序的数据元素,才能用高效的完成排序。

2. 选择哪一种排序算法最快最好?

我们可以将学过的常用数据结构在大脑中过一遍:

* 数组:可行,但是你已经有一个数组了。还要一直保持数组中的数字有序,开销会比较大了。我们暂时先不选它,但可以作为备选项。

* 链表:不太行。因为链表在随机访问和排序上性能不好。

* 二叉树:有可能行,因为二叉树在排序方面有很好的表现。如果二叉树是平衡的话,那么根节点就是中位数。但是注意,如果数组中有偶数个元素时,中位数应该是中间两个数的平均值。而根节点不可能是两个数的。结论:可能可行,待定。

* 堆:堆确在排序、查找最大值/最小值有很好的性能。如果你创建两个堆,一个是最大堆,一个最小堆。一个堆的堆顶记录数组较小一半的最大值,另外一个堆顶记录较大值的最小值。这样的结构下,两个堆如果“平衡”的话,那堆顶的数字就可能是需要的中位数了。如果两个堆”不平衡(堆的大小不一样),可以从元素多的堆中弹出堆顶的元素到另外一个堆,保持平衡。

学过的排序算法:直接插入排序、希尔排序,交换排序(气泡排序,快速排序),选择排序,堆排序,归并排序。


可能的解法:

思路1

1.1数据结构采用数组,采用普通的比较排序法把无序数组排好序,时间复杂度 O(N*logN) ;

1.2取出中间的元素即为中位数。

1.3如果采用非比较的计数排序等方法,时间复杂度O(N), 空间复杂度也是O(N).

思路2 

2.1数据结构选择堆,排序算法为堆排序法

2.2将前(n+1)/2个元素调整为一个小顶堆;

2.3对后续的每一个元素,和堆顶比较,如果小于等于堆顶,丢弃之,取下一个元素。如果大于堆顶,用该元素取代堆顶,调整堆,取下一元素。重复2.2步

2.4当遍历完所有元素之后,堆顶即是中位数。 

思路3

熟话说,想让算法跑的更快,用分治!  快速排序之所以得名"快排",绝非浪得虚名!因为快排就是一种分治排序法! 同样,找中位数也可以用快排分治的思想。

具体如下:  任意挑一个元素,以改元素为支点,划分集合为两部分,如果左侧集合长度恰为 (n-1)/2,那么支点恰为中位数。如果左侧长度<(n-1)/2, 那么中位点在右侧,反之,中位数在左侧。进入相应的一侧继续寻找中位点。  这种方法很快,但是在最坏的情况下时间复杂度为O(N^2), 不过平均时间复杂度好像是O(N)。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值