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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数组中第K大元素

發(fā)布時(shí)間:2023/12/29 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数组中第K大元素 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

數(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è)可以的思路…..恩,代碼還是貼一下,以后就省事了..

int heap_size;int parent(int idx) {return (idx - 1) >> 1; //求父節(jié)點(diǎn)}int left(int idx) {return (idx << 1) + 1;//左子樹}int right(int idx) {return (idx << 1) + 2;//右子樹}void max_heapify(vector<int>& nums, int idx) {int largest = idx;int l = left(idx), r = right(idx);if (l < heap_size && nums[l] > nums[largest]) largest = l;if (r < heap_size && nums[r] > nums[largest]) largest = r;if (largest != idx) {swap(nums[idx], nums[largest]);max_heapify(nums, largest);}}//構(gòu)建最大堆,從非葉子節(jié)點(diǎn)開始操作,可證明時(shí)間復(fù)雜度是O(n)void build_max_heap(vector<int>& nums) {heap_size = nums.size();for (int i = (heap_size >> 1) - 1; i >= 0; i--)max_heapify(nums, i);}int findKthLargest(vector<int>& nums, int k) {build_max_heap(nums);for (int i = 0; i < k; i++) {swap(nums[0], nums[heap_size - 1]);heap_size--;max_heapify(nums, 0);}//不斷交換末尾元素和最大元素,之后重新max_heapifyreturn nums[heap_size];}

快速排序思路

該思想類似快速排序:

  • 以某一個(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é)

    以上是生活随笔為你收集整理的数组中第K大元素的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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