![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { int[] ar = { 1, 25, 3, 4, 9, 6 ,9,7,10}; try { Console.WriteLine(get2rdMax(ar).ToString()); } catch (Exception exc) { Console.WriteLine(exc.Message); } Console.ReadKey(); } private static int get2rdMax(int[] ar) { int max = ar[0], s_max = ar[0]; for (int i = 0; i < ar.Length; i++) { if (ar[i] > s_max) //后面的跟第二大先比,if大,赋值给第二大, { s_max = ar[i]; //第二大再跟最大比,if还大,第二大跟最大交换 if (s_max > max) //交换。一次最终:max>s_max>ar[i] { int temp; temp = max; max = s_max ; s_max = temp ; } } } if (max == s_max) //至少有两个一样的最大值 throw new Exception("no second max!"); else return s_max; } } }
求一个数组中第k大的数,我第一印象是冒泡,因为只要冒泡k趟即可,第一趟冒泡第一大,第二次冒泡第二大,第k次冒泡第k大,时间复杂度为O(kn),n为数组长度。但是我们都知道快速排序是对冒泡的改进,降低冒泡的递归深度,使时间复杂度降低到O(nlgn),为什么不用快排呢?那么快排的时间复杂度又是多少呢?
因为快排每次将数组划分为两组加一个枢纽元素,每一趟划分你只需要将k与枢纽元素的下标进行比较,如果比枢纽元素下标大就从右边的子数组中找,如果比枢纽元素下标小从左边的子数组中找,如果一样则就是枢纽元素,找到,如果需要从左边或者右边的子数组中再查找的话,只需要递归一边查找即可,无需像快排一样两边都需要递归,所以复杂度必然降低。
最差情况如下:假设快排每次都平均划分,但是都不在枢纽元素上找到第k大
第一趟快排没找到,时间复杂度为O(n),第二趟也没找到,时间复杂度为O(n/2),。。。。。,第k趟找到,时间复杂度为O(n/2k),所以总的时间复杂度为
O(n(1+1/2+....+1/2k))=O(n),明显比冒泡快,虽然递归深度是一样的,但是每一趟时间复杂度降低。
快排求第k大数代码如下:(C#版)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 求数组第K大的数 { class Program { static void Main(string[] args) { //int[] ar = { 1, 2, 3, 4, 5, 6 ,17,28,39,7,8,9,10}; //Array.Sort(ar); //此方法实现的就是快速排序。。 //Console.WriteLine("数组中第12大的数是:"+ar[12-1]); //Console.ReadLine( ); int[] ar = { 1020, 222, 833, 834, 235, 36, 17, 28, 39, 7, 8, 9, 10 }; Console.WriteLine("表中有元素" + ar.Length + "个,下标是0—" + (ar.Length - 1)); for (int i = 0; i < ar.Length; i++) { Console.Write(ar[i] + "-"); } QuickSort(ar, 0, ar.Length - 1); //快速排序 Console.WriteLine(); for (int i = ar.Length - 1; i >= 0; i--) //从大到小排 { Console.Write(ar[i] + "-"); } Console.WriteLine("输入你想找的第K大数(正整数):"); string K = Console.ReadLine(); int k = Convert.ToInt32(K); Console.WriteLine(ar[ar.Length - k]); Console.ReadLine(); } public static void QuickSort(int[] a, int low, int high) { int i = low; int j = high; int tmp = a[low]; //分界点 while (low < high) { while ((low < high) && (a[high] >= tmp)) //后边 比tmp大的 不动 { --high; } a[low] = a[high]; //将 比tmp小的放在前面,low位置 while ((low < high) && (a[low] <= tmp)) //前面 比tmp小的 不动 { ++low; } a[high] = a[low]; //将 比tmp大的放在后面,high位置 //直到此时 low=high } a[high] = a[low] = tmp; // 此时low=high ,就完成了以tmp值来分界 //分别对前后两部分来 快速排序 if (i < low - 1) //对tmp 前面的数(0到low-1) 递归调用,,此时【low】==tmp,low=high { QuickSort(a, i, low - 1); } if (low + 1 < j) //对tmp 后面的数(low+1到j) 递归调用,,此时【low】==tmp,low=high { QuickSort(a, low + 1, j); } } } }