数组中第K大元素
數(shù)組中第K大元素
在面試的時(shí)候遇到過這個(gè)問題,后來在leetcode上也遇到了這個(gè)問題,于是記錄下來以便以后快速回憶。
題目有多種思路,全排序是比較直觀的想法,然而最低的時(shí)間復(fù)雜度為O(nlgn),并且不符合該題目的初衷。
題目更多想問的是如何在不進(jìn)行全排序的條件下找到數(shù)組中第K大的元素,個(gè)人認(rèn)為比較被面試官中意的解答有兩個(gè)(理應(yīng)也有其他的..),如下:
構(gòu)建最大堆
簡單分析時(shí)間復(fù)雜度: 構(gòu)建堆的時(shí)間O(n),k次取最大元素要k(lgn),最終的時(shí)間復(fù)雜度為O(n+klgn).
顯然是比全排序要好一些,但是當(dāng)時(shí)面試的時(shí)候我回答這個(gè)思路,面試官認(rèn)為并不是一個(gè)好的思路,因?yàn)槊嬖嚬僬J(rèn)為構(gòu)建最大堆更適合題目:求數(shù)組中前K大的元素(維護(hù)一個(gè)大小為K的最大堆).
然而我還是認(rèn)為這是一個(gè)可以的思路…..恩,代碼還是貼一下,以后就省事了..
快速排序思路
該思想類似快速排序:
以某一個(gè)元素為pivot元素,將元素分為兩個(gè)集合,一個(gè)集合元素比pivot小,另一個(gè)比pivot大。
若比pivot大的元素?cái)?shù)目正好為k-1,那么pivot就是我們要找到元素;若比pivot大的元素為m(小于k), 那么就在比pivot小的集合里面找第(k-m)大的元素; 若是比pivot大的元素為m(大于k),那就繼續(xù)在該集合里面找第k大的元素。
重復(fù)上面步驟,直到找到第k大的元素
代碼如下:
int partition(vector<int>& nums, int i, int j){//類似快速排序的分組if (i == j) return i;int pivot = nums[i];std::swap(nums[i], nums[j]);int i0 = i;for(int k = i; k < j; k ++){if(nums[k] <= pivot){std::swap(nums[k], nums[i0 ++]);}}std::swap(nums[i0], nums[j]);return i0;}int findKthEle(vector<int>& nums, int i, int j,int k){int index = partition(nums,i,j);int length = j-index+1;if(length == k)return nums[index];else if(length > k)return findKthEle(nums,index+1,j,k);else if(length <k)return findKthEle(nums,i,index-1,k-length);}int findKthLargest(vector<int>& nums, int k) {size_t len = nums.size();return findKthEle(nums,0,len-1,k);}時(shí)間復(fù)雜度:
該算法的平均時(shí)間復(fù)雜度為O(N)(詳細(xì)的推導(dǎo)過程看算法導(dǎo)論9.2節(jié)),最壞情況為N^2,即每次劃分把數(shù)組變?yōu)闉?#xff08;n-1) 和1的兩斷。
同時(shí)算法導(dǎo)論上有關(guān)于O(n)的算法(9.3節(jié)),其思路是選擇pivot元素時(shí)是通過選擇多組元素中的中位數(shù),根據(jù)這個(gè)元素來劃分,能夠得到最壞情況為線性時(shí)間的選擇算法(具體推導(dǎo)我還真是吃不消)。
看了算法導(dǎo)論以及網(wǎng)上相關(guān)的博客,發(fā)現(xiàn)這是個(gè)經(jīng)典的老題目了…然而我并沒有研究的非常透徹…
總結(jié)
- 上一篇: allegro卡死解决方法
- 下一篇: MAC挂载NTFS硬盘