日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

线性时间选择算法

發(fā)布時間:2023/12/9 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线性时间选择算法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

一,測試框架

二,平均運行時間為O(n)的算法

三,最壞運行時間為O(n)的算法

四,力扣?215. 數(shù)組中的第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)的算法

和快速排序類似,我們每次選擇一個值,把大于它的和小于它的分開成兩撥,然后只需要在其中一撥里面繼續(xù)尋找即可。

template<typename T> int Partition(T* arr, int start, int end) //[start,end]閉區(qū)間 {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作為劃分數(shù)組的分界值就一定很均衡。

時間復雜度:

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]閉區(qū)間 {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. 數(shù)組中的第K個最大元素

在未排序的數(shù)組中找到第 k 個最大的元素。請注意,你需要找的是數(shù)組排序后的第 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 ≤ 數(shù)組的長度。

代碼一:

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]閉區(qū)間 {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]閉區(qū)間 {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

總結

以上是生活随笔為你收集整理的线性时间选择算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。