最小的K个数 C++(BFPRT,堆排序)
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
//堆排序 #include <iostream> #include <algorithm> #include <vector> using namespace std; class Solution { public: void HeapAdjust(vector<int> &a,int s,int n) { int rc=a[s]; for(int j=2*s+1; j<=n-1; j=j*2+1) { if(j<n-1&&a[j]>a[j+1]) j++; if(rc<=a[j]) break; else { a[s]=a[j]; s=j; } } a[s]=rc; } void CreatHeap(vector<int> &a,int n) { for(int i=n/2-1; i>=0; i--) { HeapAdjust(a,i,n); } } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> ans; if(input.size()==0||k==0||k>input.size()) return ans; int n=input.size(); CreatHeap(input,n); for(int i=n-1; i>0; i--) { int x=input[0]; input[0]=input[i]; input[i]=x; HeapAdjust(input,0,i); } for(int i=input.size()-1;i>=0&&k>0;i--) { ans.push_back(input[i]); k--; } return ans; } }; int main() { Solution s; int k=4; vector<int> ans; vector<int> input; input.push_back(4); input.push_back(5); input.push_back(1); input.push_back(6); input.push_back(2); input.push_back(7); input.push_back(3); input.push_back(8); ans=s.GetLeastNumbers_Solution(input,k); for(int i=0; i<ans.size(); i++) { cout<<ans[i]; } return 0; }
//BFPRT #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> using namespace std; class Solution { public: vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> ans; if(input.size()==0||k==0||k>input.size()) { return ans; } for(int i=0; i<=BFPRT(input,0,input.size()-1,k); i++) { ans.push_back(input[i]); } return ans; } /* 插入排序,返回中位数下标 */ int InsertSort(vector<int> &array, int left, int right) { int temp; int j; for (int i = left + 1; i <= right; i++) { temp = array[i]; j = i - 1; while (j >= left && array[j] > temp) array[j + 1] = array[j--]; array[j + 1] = temp; } return ((right - left) >> 1) + left; } /* 返回中位数的中位数下标 */ int GetPivotIndex(vector<int> &array, int left, int right) { if (right - left < 5) return InsertSort(array, left, right); int sub_right = left - 1; for (int i = left; i + 4 <= right; i += 5) { int index = InsertSort(array, i, i + 4); //找到五个元素的中位数的下标 swap(array[++sub_right], array[index]); //依次放在左侧 } return BFPRT(array, left, sub_right, ((sub_right - left + 1) >> 1) + 1); } /* 利用中位数的中位数的下标进行划分,返回分界线下标 */ int Partition(vector<int> &array, int left, int right, int pivot_index) { swap(array[pivot_index], array[right]); //把基准放置于末尾 int divide_index = left; //跟踪划分的分界线 for (int i = left; i < right; i++) { if (array[i] < array[right]) swap(array[divide_index++], array[i]); //比基准小的都放在左侧 } swap(array[divide_index], array[right]); //最后把基准换回来 return divide_index; } int BFPRT(vector<int> &array, int left, int right, const int & k) { int pivot_index = GetPivotIndex(array, left, right); //得到中位数的中位数下标 int divide_index = Partition(array, left, right, pivot_index); //进行划分,返回划分边界 int num = divide_index - left + 1; if (num == k) return divide_index; else if (num > k) return BFPRT(array, left, divide_index - 1, k); else return BFPRT(array, divide_index + 1, right, k - num); } }; int main() { Solution s; int k=4; vector<int> ans; vector<int> input; input.push_back(4); input.push_back(5); input.push_back(1); input.push_back(6); input.push_back(2); input.push_back(7); input.push_back(3); input.push_back(8); ans=s.GetLeastNumbers_Solution(input,k); for(int i=0; i<ans.size(); i++) { cout<<ans[i]; } return 0; }