博主内推:阿里菜鸟网络春招 【部门直推】【海量实习岗位&正式岗位】
问题描述:给一个无序数组,找到其中位数,并说出该算法的时间复杂度以及空间复杂度。
解题方法一:
中位数:当数组元素个数为奇数n时,中位数=a[n/2]。当元素个数为偶数时,中位数=( a[n / 2] + a[ ( n + 1 ) / 2 ])
按照这个中位数定义来求解。利用快速排序对数组进行排序,时间复杂度为O(nlogn) 空间复杂度为S(1); 之后的找到中位数所用时间复杂度为O(1) 空间复杂度为O(1)
解题方法二:
在了解方法二之前我们先来了解一下快速排序。对于快排算法,其中主元的选择对于数组的划分起到很大的影响,从而对于运行时间产生很大的影响。当主元不能很好地分割数组,即主元将数组分成一个子数组中有一个记录,而另一个子组组有 n -1 个记录时,下一次的子数组只比原来数组小 1,这是快速排序的最差的情况。如果这种情况发生在每次划分过程中,那么快速排序就退化成了冒泡排序,其时间复杂度为O(n2)。老师曾经举过一个例子:甲、乙两同学去比较各自排序算法的好坏,他们可以互相阅读对方的原代码,然后互相给对方提供无序数组,最后比较那个运行比较快。乙同学看到甲同学的快排的代码,乙同学针对甲同学的代码专门写了所谓的无序数组(并非无序数组,只是甲同学的代码在解决这个无序数组的排序中会退化成冒泡排序)。然而甲同学看到乙同学的快排代码之后就老老实实的给了无序数组。为什么甲同学没有去找针对于乙同学的那个能够导致退化的无序数组呢?原因就是乙同学的快排主元的选择是随机化的。
随机化排序代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 int partition(int *a,int p,int r); 4 int random_partition(int *a,int p,int r); 5 int random_select(int *a,int p,int r,int i); 6 int main() 7 { 8 9 system("pasue"); 10 return 0; 11 } 12 int partition(int *a,int p,int r) 13 { 14 int x=a[r],t; 15 int i=p-1,j; 16 for(j=p;j<=r-1;j++) 17 { 18 if(a[j]<=x)//如果要降序排列,则改为if(a[j]>=x) 19 { 20 i++; 21 t=a[i]; 22 a[i]=a[j]; 23 a[j]=t; 24 } 25 } 26 t=a[i+1]; 27 a[i+1]=a[r]; 28 a[r]=t; 29 return i+1; 30 } 31 int random_partition(int *a,int p,int r) 32 { 33 int t,i; 34 i=p+(int)((r-p+1)*rand()/(RAND_MAX+1.0));//利用随机数随机选择用于分割的元素,注意范围 35 t=a[i]; 36 a[i]=a[r]; 37 a[r]=t; 38 return partition(a,p,r); 39 } 40 int random_select(int *a,int p,int r,int i)//找出a[p]——a[r]之间第i小的元素 41 { 42 int q; 43 if(p==r) 44 return a[p]; 45 q=random_partition(a,p,r); 46 int k=q-p+1; 47 if(i==k) 48 return a[q]; 49 else if(i<k) 50 return random_select(a,p,q-1,i); 51 else 52 return random_select(a,q+1,r,i-k); 53 }