线性时间选择算法
目錄
一,測試框架
二,平均運行時間為O(n)的算法
三,最壞運行時間為O(n)的算法
四,力扣?215. 數組中的第K個最大元素
背景:
給出n個元素,在O(n)的時間內找出第i小的元素。
一,測試框架
和排序算法常見排序算法_csuzhucong的博客-CSDN博客一文類似:
#include <iostream> using namespace std;template<typename T> bool cmp(T a, T b) {return a < b; } template<typename T> void exchange(T* a, T* b) {T tmp = *a;*a = *b;*b = tmp; }template<typename T> T Select(T* arr, int len, int ith) {return ...... }int main() {int arr[] = { 1,4,2,6,3,8,9,7 };cout << Select(arr, sizeof(arr) / sizeof(int), 3);return 0; }二,平均運行時間為O(n)的算法
和快速排序類似,我們每次選擇一個值,把大于它的和小于它的分開成兩撥,然后只需要在其中一撥里面繼續尋找即可。
template<typename T> int Partition(T* arr, int start, int end) //[start,end]閉區間 {T x = arr[end];int i = start - 1;for (int j = start; j < end; j++) {if (cmp(arr[j], x)) {exchange(arr + ++i, arr + j);}}exchange(arr + ++i, arr + end);return i; }template<typename T> T Select(T* arr, int len, int ith) {if (len <= 1)return arr[0];int part = Partition(arr, 0, len - 1);if (ith == part)return arr[ith];if (ith < part)return Select(arr, part, ith);return Select(arr + part + 1, len - part - 1, ith - part - 1); }平均時間為O(n),最壞時間為O(n^2)
三,最壞運行時間為O(n)的算法
算法思路:
分析:
可以證明至少有3n/10-6個元素大于x,也至少有3n/10-6個元素小于x,所以用x作為劃分數組的分界值就一定很均衡。
時間復雜度:
T(n)= T(n/5) + T(7n/10+6) + O(n)
可以推算出,T(n)=?O(n)
代碼:
#include <iostream> #include<algorithm> using namespace std;template<typename T> bool cmp(T a, T b) {return a < b; } template<typename T> void exchange(T* a, T* b) {T tmp = *a;*a = *b;*b = tmp; }template<typename T> int Partition(T* arr, int start, int end, T x) //[start,end]閉區間 {int i = start - 1;for (int j = start; j < end; j++) {if (arr[j] == x)exchange(arr + j, arr + end);if (cmp(arr[j], x)) {exchange(arr + ++i, arr + j);}}exchange(arr + ++i, arr + end);return i; }template<typename T> T Select(T* arr, int len, int ith);template<typename T> T SelectPart(T* arr, int len) {if (len < 5)return arr[0];int z = len / 5;T* p = new T[z];for (int i = 0; i < z; i++) {sort(arr + i * 5, arr + i * 5 + 5, cmp<T>);p[i] = arr[i * 5 + 2];}return Select(p, z, z / 2); }template<typename T> T Select(T* arr, int len, int ith) {if (len <= 1)return arr[0];T parti = SelectPart(arr, len);int part = Partition(arr, 0, len - 1, parti);if (ith == part)return arr[ith];if (ith < part)return Select(arr, part, ith);return Select(arr + part + 1, len - part - 1, ith - part - 1); }int main() {int arr[] = { 1,4,2,6,3,8,9,7 };cout << Select(arr, sizeof(arr) / sizeof(int), 3);return 0; }四,力扣?215. 數組中的第K個最大元素
在未排序的數組中找到第 k 個最大的元素。請注意,你需要找的是數組排序后的第 k 個最大的元素,而不是第 k 個不同的元素。
示例 1:
輸入: [3,2,1,5,6,4] 和 k = 2
輸出: 5
示例?2:
輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4
輸出: 4
說明:
你可以假設 k 總是有效的,且 1 ≤ k ≤ 數組的長度。
代碼一:
template<typename T> bool cmp(T a, T b) {return a < b; } template<typename T> void exchange(T* a, T* b) {T tmp = *a;*a = *b;*b = tmp; } template<typename T> int Partition(T* arr, int start, int end) //[start,end]閉區間 {T x = arr[end];int i = start - 1;for (int j = start; j < end; j++) {if (cmp(arr[j], x)) {exchange(arr + ++i, arr + j);}}exchange(arr + ++i, arr + end);return i; }template<typename T> T Select(T* arr, int len, int ith) {if (len <= 1)return arr[0];int part = Partition(arr, 0, len - 1);if (ith == part)return arr[ith];if (ith < part)return Select(arr, part, ith);return Select(arr + part + 1, len - part - 1, ith - part - 1); }template<typename T> T* vecToArr(vector<T>& v) {return v.data(); }class Solution { public:int findKthLargest(vector<int>& nums, int k) {return Select(vecToArr(nums),nums.size(),nums.size()-k);} };56ms AC
代碼二:
template<typename T> bool cmp(T a, T b) {return a < b; } template<typename T> void exchange(T* a, T* b) {T tmp = *a;*a = *b;*b = tmp; } template<typename T> int Partition(T* arr, int start, int end, T x) //[start,end]閉區間 {int i = start - 1;for (int j = start; j < end; j++) {if (arr[j] == x)exchange(arr + j, arr + end);if (cmp(arr[j], x)) {exchange(arr + ++i, arr + j);}}exchange(arr + ++i, arr + end);return i; }template<typename T> T Select(T* arr, int len, int ith);template<typename T> T SelectPart(T* arr, int len) {if (len < 5)return arr[0];int z = len / 5;T* p = new T[z];for (int i = 0; i < z; i++) {sort(arr + i * 5, arr + i * 5 + 5, cmp<T>);p[i] = arr[i * 5 + 2];}return Select(p, z, z / 2); }template<typename T> T Select(T* arr, int len, int ith) {if (len <= 1)return arr[0];T parti = SelectPart(arr, len);int part = Partition(arr, 0, len - 1, parti);if (ith == part)return arr[ith];if (ith < part)return Select(arr, part, ith);return Select(arr + part + 1, len - part - 1, ith - part - 1); }template<typename T> T* vecToArr(vector<T>& v) {T* p = new T[v.size()];for (int i = 0; i < v.size(); i++)p[i] = v[i];return p; }class Solution { public:int findKthLargest(vector<int>& nums, int k) {return Select(vecToArr(nums),nums.size(),nums.size()-k);} };8ms AC
總結
- 上一篇: 前端学习(3063):vue+eleme
- 下一篇: python取绝对值fab_Python