A method to find the KTH largest number in an array in linear time complexity

  • 2020-04-01 23:44:42
  • OfStack

The KTH largest number in the array can be calculated based on the idea of fast sorting. The steps are as follows:
1. Choose a fulcrum at random
2. Put the number larger than the fulcrum to the left of the array; Put the number smaller than the fulcrum to the right of the array; Put the fulcrum in the middle (to the left)
3. Let the length of the left part be L,
When K < For L, recursively look for the KTH largest number on the left
When K > In the case of L, recursively look for the largest number (K - L) in the number
When K = L, the dividing point of the left and right parts (i.e. the original fulcrum) is returned, which is the KTH largest number
The code implementation of the above ideas is as follows:


#include "iostream"
using namespace std;
//Based on the idea of quicksort, the KTH largest number in array a is calculated. Low and high are respectively the starting and ending positions of the array
//The time complexity is o(n), and n is the length of the array
//1<=k<=n
//Returns the index of the KTH largest number if it exists, or -1 if it does not
int selectk(int a[], int low, int high, int k)
{
 if(k <= 0)
  return -1;
 if(k > high - low + 1)
  return -1;
 int pivot = low + rand()%(high - low + 1);    //Then choose a fulcrum
 swap(a[low], a[pivot]);
 int m = low;
 int count = 1;
 //I'm going to go through it once, and I'm going to put the larger Numbers on the left side of the array
 for(int i = low + 1; i <= high; ++i)
 {
  if(a[i] > a[low]) 
  {
   swap(a[++m], a[i]);
   count++;              //The number of Numbers larger than the fulcrum is count minus 1
  }
 }
 swap(a[m], a[low]);           //Place the fulcrum at the boundary between the left and right parts
 if(count > k)
 {
  return selectk(a, low, m - 1, k);
 }
 else if( count < k)
 {
  return selectk(a, m + 1, high, k - count);
 }
 else
 {
  return m;
 }
}
int main(void)
{
 int a[] = {5, 15, 5, 7, 9, 17,100, 3, 12, 10, 19, 18, 16, 10, 1000,1,1,1,1,1,1,1,1};
 int r = selectk(a, 0, sizeof(a) /sizeof(int) - 1, 5);
 cout<<(r == -1 ? r : a[r])<<endl;
 system("pause");
 return 0;
}

If you change it a little bit, you can change it to the KTH decimal in the array
The complete code is as follows:


#include "iostream"
using namespace std;
//Based on the idea of quicksort, the KTH smallest number in array a is calculated. Low and high are respectively the starting and ending positions of the array
//The time complexity is o(n), and n is the length of the array
//1<=k<=n
//Returns the index of the KTH decimal if it exists, or -1 if it does not
int selectk(int a[], int low, int high, int k)
{
 if(k <= 0)
  return -1;
 if(k > high - low + 1)
  return -1;
 int pivot = low + rand()%(high - low + 1);    //Then choose a fulcrum
 swap(a[low], a[pivot]);
 int m = low;
 int count = 1;
 //I'm going to go through it once, and I'm going to put the smaller Numbers on the left side of the array
 for(int i = low + 1; i <= high; ++i)
 {
  if(a[i]<a[low]) 
  {
   swap(a[++m], a[i]);
   count++;              //The number of Numbers less than the fulcrum is count minus 1
  }
 }
 swap(a[m], a[low]);           //Place the fulcrum at the boundary between the left and right parts
 if(k < count)
 {
  return selectk(a, low, m - 1, k);
 }
 else if( k > count)
 {
  return selectk(a, m + 1, high, k - count);
 }
 else
 {
  return m;
 }
}
int main(void)
{
 int a[] = {5, 15, 5, 7, 9, 17,100, 3, 12, 10, 19, 18, 16, 10, 1000,1,1,1,1,1,1,1,1};
 int r = selectk(a, 0, sizeof(a) /sizeof(int) - 1, 23);
 cout<<(r == -1 ? r : a[r])<<endl;
 system("pause");
 return 0;
}

Related articles: