算法:前K個最大的元素

前幾天,阮一峰 和 winter 在前端九部組織了一個互面小組,目的是為了分享和解答面試遇到的面試題,感興趣的可以了解一下。

下面我就把我回答的一個問題整理出來分享給大家。

問題描述

題目是:算法,前 K 個最大的元素。

這個題目非常簡短,第一眼看上去可能不知道是什么意思。翻譯一下:

給定一個數字類型的數組和一個正整數 K,找出數組中前 K 個最大的元素。

這個題目網速也有很多的講解,我也是根據網上提供的一些思路來實現的,下面就是我根據其中三種方法的實現:

解答

解法一:

思路

最簡單的方法就是對數組進行排序,然后取前 K 位就可以了。

實現

/*** 查找前 K 個最大的元素* * @param {number[]} arr - 要查詢的數組* @param {number} k - 最大個數* * @return {number[]}*/
const findKMax = (arr, k) => {return arr.sort((a, b) => b - a).slice(0, k);
}
復制代碼

解法二

思路

解法一用了 js 的 sort 來實現排序,但是復雜度比較高,數據量大的話會比較慢。仔細分析一下題目,找出前 K 個最大的元素,但并沒有要求對其排序,所以不用對所有的數都進行排序。分治法就會快很多:

假設有 n 個數存在數組 S 中,從數組 S 中隨機找一個元素 X,遍歷數組,比 X 大的放在 S1 中,比 X 小的放在 S2 中,那么會出現以下三種情況:

S1 的數字個數等于 K,結束查找,返回 S1; S1 的數字個數大于 K,繼續在 S1 中找取最大的K個數字; S1 的數字個數小于 K,繼續在 S2 中找取最大的 K-S1.length 個數字,拼接在 S1 后; 這樣遞歸下去,就可以找出答案來了。下面看具體的實現:

實現

/*** 分割數組* * @typedef {Object} Partition* @property {number[]} Partition.maxarr* @property {number[]} Partition.minarr* * @param {number[]} arr - 要分割的數組* * @returns {Partition} res - 返回結果*/
const partition = (arr) => {const length = arr.length; // 數組長度const mid = ~~(length / 2); // 取數組中間的位置,可隨機const middle = arr[mid]; // 數組中間的值const maxarr = []; // 比中間值大const minarr = []; // 比中間值小// 數組長度為 2 的要特殊處理if (length === 2) {maxarr.push(Math.max(arr[0], arr[1]));minarr.push(Math.min(arr[0], arr[1]));} else {arr.forEach((v, i) => {if (i !== mid) {if (v >= middle) {maxarr.push(v);} else {minarr.push(v);}}})// 將中間值放到 maxarr 的最后一位maxarr.push(middle);}return { maxarr, minarr }
}/*** 查找前 K 個最大的元素* * @param {number[]} arr - 要查詢的數組* @param {number} k - 最大個數* * @return {number[]}*/
const findKMax = (arr, k) => {if (arr.length < k) {return arr;}// 分割數組const { maxarr, minarr } = partition(arr);if (maxarr.length === k) {return maxarr;}if (maxarr.length > k) {return findKMax(maxarr, k);}if (maxarr.length < k) {return maxarr.concat(findKMax(minarr, k - maxarr.length));}
}
復制代碼

解法三

思路

可以取數組的前 K 位構建一個小頂堆(也叫最小堆),這么堆頂就是前 K 位最小的值,然后從 K+1 遍歷數組,如果小于堆頂,則將其交換,并重新構建堆,使堆頂最小,這么遍歷結束后,堆就是最大的 K 位,堆頂是前 K 位的最小值。

實現

/*** 小頂堆葉子節點排序* @param {number[]} arr - 堆* @param {number} i = 父節點* @param {length} i - 堆大小*/
const heapify = (arr, i, length) => {const left = 2 * i + 1; // 左孩子節點const right = 2 * i + 2; // 右孩子節點let minimum = i; // 假設最小的節點為父結點// 確定三個節點的最小節點if (left < length && arr[left] < arr[minimum]) {minimum = left;}if (right < length && arr[right] < arr[minimum]) {minimum = right;}// 如果父節點不是最小節點if (minimum !== i) {// 最小節點和父節點交換const tmp = arr[minimum];arr[minimum] = arr[i];arr[i] = tmp;// 對調整的結點做同樣的交換heapify(arr, minimum, length);}}/*** 構建小頂堆* 從 n/2 個節點開始,依次構建堆,直到第一個節點* * @param {number[]} arr */
const buildMinHeap = (arr) => {for (let i = Math.floor(arr.length / 2); i >= 0; i--) {heapify(arr, i, arr.length)}return arr;
}/**·* 查找前 K 個最大的元素* * @param {number[]} arr - 要查詢的數組* @param {number} k - 最大個數* * @return {number[]}*/
const findKMax = (arr, k) => {// 取數組的前 K 位構建小頂堆const newArr = [...arr];const kMax = arr.slice(0, k)buildMinHeap(kMax);// 堆后面的進行遍歷,如果比堆頂大,則交換并重新構建堆for (let i = k; i < newArr.length; i++) {if (newArr[i] > kMax[0]) {const tmp = kMax[0];kMax[0] = newArr[i];newArr[i] = tmp;buildMinHeap(kMax);}}return kMax;
}
復制代碼

總結

上面就是我對這個題目的三種解法,其實還有幾種解法,因為精力原因沒有探究,大家可以自己去網上了解一下。

上述解法如果有問題還請指正。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279545.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279545.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279545.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

php表單提交完返回,表單內容不清空解決方法

2019獨角獸企業重金招聘Python工程師標準>>> 我們經常在注冊的時候&#xff0c;填寫一大推信息以后在提交注冊的時候&#xff0c;因為某一項信息不正確&#xff0c;在返回的時候之前的填寫的內容全部沒有了&#xff0c;這樣會導致用戶喪失再次填寫的信息&#xff0c…

es6拼接字符串的方式。

文章&#xff1a;es6拼接字符串的方式。轉載于:https://www.cnblogs.com/Tpf386/p/9519007.html

word標尺灰色_如何在Microsoft Word中使用標尺

word標尺灰色Word’s rulers let you control the margins of your page and the indentation of paragraphs. They’re great for precisely lining up images, text, and other elements. If you’re printing a document, the rulers can help ensure that what you see on …

drools簡單應用

當某個服務的需求經常變的時候&#xff0c;如果使用了硬編碼的方式進行開發會是一件非常麻煩的事。 最近在對項目的積分模塊進行改造的時候想到了規則引擎&#xff0c;使用規則引擎處理復雜而且多變的業務邏輯有其非常大的優勢&#xff0c;包括實時更新、性能等方面。 不多說&a…

31 天重構學習筆記28. 為布爾方法命名

摘要&#xff1a;由于最近在做重構的項目&#xff0c;所以對重構又重新進行了一遍學習和整理&#xff0c;對31天重構最早接觸是在2009年 10月份&#xff0c;由于當時沒有訂閱Sean Chambers的blog&#xff0c;所以是在國外的社區上閑逛的時候鏈接過去的。記得當時一口氣看完了整…

Matplotlib學習---用matplotlib畫誤差線(errorbar)

誤差線用于顯示數據的不確定程度&#xff0c;誤差一般使用標準差&#xff08;Standard Deviation&#xff09;或標準誤差&#xff08;Standard Error&#xff09;。 標準差&#xff08;SD&#xff09;&#xff1a;是方差的算術平方根。如果是總體標準差&#xff0c;那么用σ表示…

關于自增id 你可能還不知道

導讀&#xff1a;在使用MySQL建表時&#xff0c;我們通常會創建一個自增字段(AUTO_INCREMENT)&#xff0c;并以此字段作為主鍵。本篇文章將以問答的形式講述關于自增id的一切。 注&#xff1a; 本文所講的都是基于Innodb存儲引擎。 1.MySQL為什么建議將自增列id設為主鍵&#x…

Android One和Android Go有什么區別?

In 2014, Google announced a lineup of low-cost, low-spec phones called Android One. In 2017, they announced Android Go, specifically designed for low-cost, low-spec phones. So…what’s the difference? 2014年&#xff0c;Google宣布了一系列名為Android One的低…

outlook advanced find 快捷鍵不起作用

癥狀&#xff1a;用戶反應按outlook advanced find的快捷鍵時無效&#xff0c;快捷鍵為CtrlShiftF。第一感覺是肯定跟別的軟件有沖突了&#xff0c;觀察了下&#xff0c;發現用戶正在使用sougou拼音輸入法&#xff0c;于是點其屬性查看&#xff0c;果然發現與其的簡繁切換沖突了…

vue1.0和vue2.0生命周期----整理一

## 1. 作用域區別   1.x 隨意的定義作用域   2.x 不允許body 或者html 元素 ## 2. 生命周期   1.x:     created 實例已經創建     beforeCompile 在編譯之前     compiled 編譯之后     ready 實例已經插入到文檔之中     beforeDetroy 在銷毀之前 …

21-while里的break簡單用法

break是結束循環&#xff0c;break之后、循環體內代碼不再執行。 while True:yn input(Continue(y/n): )if yn in [n,N]:breakprint(running......) 結果輸出&#xff1a; 轉載于:https://www.cnblogs.com/hejianping/p/10861816.html

視頻造假_如何發現“深造假”面部切換視頻

視頻造假Recently, Reddit has been making news again with a subreddit in w hich people use a machine learning tool called “Deep Fake” to automatically replace one person’s face with another in a video. Obviously, since this is the internet, people are us…

C#實現MD5加密

C#實現MD5加密。 1、創建MD5Str.cs加密處理類 [csharp] view plaincopy public class MD5Str { /// <summary> /// 字符串MD5加密 /// </summary> /// <param name"Text">要加密的字符串</param> /// <returns…

【agc004f】Namori Grundy

那個問一下有人可以解釋以下這個做法嘛&#xff0c;看不太懂QwQ~ Description 有一個n個點n條邊的有向圖&#xff0c;點的編號為從1到n。 給出一個數組p&#xff0c;表明有&#xff08;p1&#xff0c;1&#xff09;&#xff0c;&#xff08;p2&#xff0c;2&#xff09;&#x…

找到特定ip地址 修改ip_您如何找到網站的IP地址?

找到特定ip地址 修改ipWhether you are in it just for a bit of geeky fun, or are seriously wanting to know the answer, how do you find out the IP address for a website? Today’s SuperUser Q&A post looks at the answer, and how to know if more than one we…

Rational Rose 2003 下載、破解及安裝方法(圖文)

方法一&#xff1a; 1、安裝Rational Rose2003時&#xff0c;在需選擇安裝項的時候&#xff0c;只選擇Rational Rose EnterPrise Edition即可&#xff0c;不需選擇其他項&#xff0c;之后選擇“DeskTop Installation from CD Image“&#xff0c;一路下一步。出現Mem_pointer_B…

數據結構:莫隊

莫隊算法是用來處理一類無修改的離線區間詢問問題 莫隊的精髓就在于&#xff0c;離線得到了一堆需要處理的區間后&#xff0c;合理的安排這些區間計算的次序以得到一個較優的復雜度 代表題目是BZOJ2038這道題 進行區間詢問[l,r]&#xff0c;輸出該區間內隨機抽兩次抽到相同顏色…

【學習筆記】第三章 python3核心技術與實踐--Jupyter Notebook

可能你已經知道&#xff0c;Python 在 14 年后的“崛起”&#xff0c;得益于機器學習和數學統計應用的興起。那為什么 Python 如此適合數學統計和機器學習呢&#xff1f;作為“老司機”的我可以肯定地告訴你&#xff0c;Jupyter Notebook &#xff08;https://jupyter.org/&…

二進制安位處理_處理器與安??全性之間的聯系是什么?

二進制安位處理Newer processors are able to contribute to the security of your system, but what exactly do they do to help? Today’s Super User Q&A post looks at the link between processors and system security. 較新的處理器能夠為您的系統安全做出貢獻&am…

李開復現身說法成功的十個啟發

http://blog.sina.com.cn/kaifulee自信不失謙虛&#xff0c;謙虛不失自信天賦就是興趣 興趣就是天賦思考比傳道重要 觀點比解惑重要我不同意你 但我支持你挫折不是懲罰 而是學習的機會創新不重要 有用的創新才重要完美的工作 成長興趣 影響力用勇氣改變可以改變的事情做最好的領…