主元素,中位数以及快速排序问题(分治法问题)

来源:互联网 发布:美非农就业数据 编辑:程序博客网 时间:2024/06/06 18:01
IBM最后有道求主元素的题目,一个数组有N个元素,其中有超过N/2的元素相同,请找出这个元素。时间复杂度为O(n)方法1:如果一个元素的个数超过N/2则这个元素必然是这N个元素的中位数。则这个题目是找中位数。方法是通过快速排序变化的来的算法。代码如下:做这个题目复习了下快排,选择一个pivot,然后围绕这个pivot将数组分成两部分,左边一部分的元素都小于pivot,右边部分的元素都大于pivot,然后递归的处理左右两个部分,直到数组元素个数为1.找第k小元素的方法是基于快排的分割函数,将一个数组分割成两部分。如果小于pivot的元素个数A小于k,则在分割后的数组的右边找第k-A小的元素,否则在左边部分找。对于中位数就是第n/2小的数。根据算法导论的说明,快排的平均算法复杂度为O(nlogn),而找第k小元素的平均算法复杂度为O(n)。找k小的算法和快排的不同在于快排需要递归处理左边和右边两个部分,即复杂度方程为:        O(1)       n = 1 T(n)={        2T(n/2)   n> 1而对于求第k小数,只需要递归处理一个分支,所以复杂度方程为:        O(1)       n = 1T(n)={        T(n/2)     n> 1虽然只比快排少了个系数2,但是可以推导出来求第k小数的复杂度为O(n),而快排为O(nlogn)方法2:求众数的方法:对于找主元素的题目,还有其他的做法,可以使用求众数的方法,首先选择一个pivot,然后将数组分割成两部分,左边的小于pivot,右边的大于pivot在分割过程中统计数组中等于pivot的元素个数,小于pivot的元素个数以及大于pivot的元素个数。如果pivot的元素个数大于等于n/2,则pivot就是所求元素。如果小于pivot的元素个数大于等于n/2,则在左边部分找,否在在右边部分找。代码为:在统计pivot出现次数时需要注意是在交换i,j对应元素时判断的。因为只有当array[i]>=x并且array[j]<=x才需要交换元素。同时当退出While(i<j)时,需要判断i==j&&Array[j]==pivot的情况,因为i==j的情况在while中是没有处理的,所以必须在while外处理。当统计得到pivot的出现次数后可以进行递归。如pivot出现的次数大于等于n/2,则返回pivot,否在向元素个数大的那部分数组递归。
方法3:主元素查找:

关于这种主元素还有种更加巧妙地方法,没看到过一定想不到的。这种方法的原理是如果一个数组中存在一个主元素(个数大于n/2),则同时删除两个不相等的值,这个主元素不会改变。
简单的说就一个大小为n数组中存在一个元素的个数大于n/2,则如果用这个数组中其他元素和该主元素进行抵消的话,最后剩下的一定是主元素,因为主元素个数最多。
该方法可以在O(n)的时间内找到主元素,十分高效。
代码:

关键的算法在找seed过程中,假设第一个元素是主元素,遍历数组,如果遇到和seed相同的元素则加1,不同则减1,如果count==0了,则seed改变。
该方法的基础就是如果存在一个值是主元素,那么遍历一遍则出现的次数一定要大于其他所有元素的次数,所以最后主元素的count一定大于0.