LeetCode-215. 數組中的第K個最大元素

1、題目描述

給定整數數組?nums?和整數?k,請返回數組中第?k?個最大的元素。

請注意,你需要找的是數組排序后的第?k?個最大的元素,而不是第?k?個不同的元素。

你必須設計并實現時間復雜度為?O(n)?的算法解決此問題。

示例 1:

輸入: [3,2,1,5,6,4], k = 2
輸出: 5

示例?2:

輸入: [3,2,3,1,2,4,5,5,6], k = 4
輸出: 4

2、代碼實現

會超時的代碼

class Solution
{
public:int findKthLargest(vector<int>& nums, int k){int target = k - 1;int left = 0, right = nums.size() - 1;while (left <= right) {int pos = partition(nums, left, right);if (pos == target) {return nums[pos];}else if (pos < target) {left = pos + 1;}else {right = pos - 1;}}return -1;}int partition(vector<int>& nums, int left, int right){static bool initSrand = false;if (!initSrand) {srand(time(0));}int pivot_index = left + (rand() % (right - left + 1));int pivot = nums[pivot_index];swap(nums[right], nums[pivot_index]);int i = left - 1;int j;for (j = left; j < right; j++) {if (nums[j] > pivot) {swap(nums[j], nums[++i]);}}swap(nums[++i], nums[right]);return i;}
};

正確的代碼

#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <tuple>
#include <vector>using namespace std;class Solution {
public:/*** @brief 在未排序數組中找到第k大的元素(基于三向切分的快速選擇算法)* @param nums 待搜索的整數數組* @param k 目標元素的排序位置(第k大)* @return 第k大的元素值* * @note 時間復雜度:平均O(n),最壞O(n2)(但概率極低)* @note 空間復雜度:O(1) 原地操作*/int findKthLargest(vector<int>& nums, int k) {int left = 0, right = nums.size() - 1;  // 當前搜索范圍while (true) {// 隨機選擇基準值避免最壞情況int pivot_idx = left + rand() % (right - left + 1);int pivot = nums[pivot_idx];// 三向切分數組(大于區|等于區|小于區)auto [greater_end, less_start] = threeWayPartition(nums, left, right, pivot);// 計算各區域元素數量int greater_cnt = greater_end - left;      // 大于區的元素數量int equal_cnt = less_start - greater_end + 1; // 等于區的元素數量/* 決策樹 */if (k <= greater_cnt) {          // 目標在大于區right = greater_end - 1;    // 縮小搜索范圍到左區} else if (k <= greater_cnt + equal_cnt) { // 命中等于區return pivot;               // 直接返回結果} else {                        // 目標在小于區k -= (greater_cnt + equal_cnt); // 調整k的相對位置left = less_start + 1;      // 縮小搜索范圍到右區}}}private:/*** @brief 三向切分數組* @param nums 待切分數組* @param left 當前處理區間的左邊界* @param right 當前處理區間的右邊界* @param pivot 基準值* @return tuple<int, int> 返回兩個邊界位置:*         - greater_end: 大于區的結束位置(最后一個大于元素的下一位置)*         - less_start: 小于區的開始位置(第一個小于元素的前一位置)* * @note 切分結果:*        [left, greater_end)    > pivot*        [greater_end, less_start] == pivot*        (less_start, right]    < pivot*/tuple<int, int> threeWayPartition(vector<int>& nums, int left, int right, int pivot)                 {int greater_end = left;   // 大于區的右邊界(左側元素均>pivot)int less_start = right;   // 小于區的左邊界(右側元素均<pivot)int i = left;             // 當前掃描指針while (i <= less_start) { // 掃描未處理區域if (nums[i] > pivot) {// 將大元素交換到大于區末尾swap(nums[i++], nums[greater_end++]);} else if (nums[i] == pivot) {// 等于元素直接跳過++i;} else {// 將小元素交換到小于區頭部(注意i不遞增)swap(nums[i], nums[less_start--]);}}return {greater_end, less_start};}
};

3、解題思路

這道題的難度很高,我最開始是采用普通的快速選擇,雖然答案是對的,但是會超時,所以我們該用三向切分策略,也就是將數組分為[left, greater_end)、[greater_end, less_start]、(less_start, right] 三個區間,不過需要注意一下開閉區間。

核心思想
  1. ?隨機化基準值
    每次隨機選擇基準值 (pivot),有效避免輸入數據有序導致的 O(n2) 最壞時間復雜度。

  2. ?三向切分 (3-Way Partition)
    將數組劃分為三個區域:

    • ?大于區:所有元素 > pivot
    • ?等于區:所有元素 == pivot
    • ?小于區:所有元素 < pivot
  3. ?遞歸決策
    根據各區域元素數量與k值的關系,決定后續搜索方向:

    • 若k在 ?大于區:縮小范圍到左區間
    • 若k在 ?等于區:直接返回pivot
    • 若k在 ?小于區:調整k值后搜索右區間
執行流程
  1. ?初始化搜索范圍
    初始處理整個數組 (left=0, right=n-1)

  2. ?隨機選擇基準值
    在?[left, right]?區間隨機選取一個元素作為基準值,確保算法魯棒性

  3. ?三向切分操作

    • 使用三個指針:
      • greater_end:標記大于區的右邊界
      • less_start:標記小于區的左邊界
      • i:當前掃描指針
    • 掃描過程:
      • 大元素 → 交換到大于區末尾,指針右移
      • 等于元素 → 跳過
      • 小元素 → 交換到小于區頭部,指針不動(需重新檢查)
  4. 決策邏輯

if (k <= greater_cnt) { ? ? ? ? ?// 目標在左區
? ? right = greater_end - 1; ? ?
} else if (k <= greater_cnt + equal_cnt) { // 命中等于區
? ? return pivot; ? ? ? ? ? ? ??
} else { ? ? ? ? ? ? ? ? ? ? ? ?// 目標在右區
? ? k -= (greater_cnt + equal_cnt);?
? ? left = less_start + 1; ? ? ?
}

常見疑問解答
  1. ?為什么用隨機pivot?

    • 避免最壞時間復雜度,保證算法平均性能
  2. ?less_start指針為何不遞增i?

    • 交換后的元素來自未處理區域,需重新判斷其值
  3. ?如何處理重復元素?

    • 三向分區將相同元素集中在中間區域,減少無效比較

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

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

相關文章

分布式光伏防逆流管理:技術要點與實踐解析

在國家“雙碳”目標推動下&#xff0c;分布式光伏作為新能源體系的重要組成部分&#xff0c;正迎來快速發展。國家能源局近期發布的《關于做好新能源消納工作保障新能源高質量發展的通知》明確提出&#xff0c;需加強網源協調與調節能力&#xff0c;優化新能源利用率。其中&…

Ubuntu capolar 上實現內網穿透

在官網https://www.cpolar.com/ 注冊用戶&#xff0c;獲取tocken 1.1 安裝cpolar 在Ubuntu上打開終端&#xff0c;執行命令 首先&#xff0c;我們需要安裝curl&#xff1a; sudo apt-get install curl 國內安裝&#xff08;支持一鍵自動安裝腳本&#xff09; curl -L htt…

【CSS】CSS 使用全教程

CSS 使用全教程 介紹 CSS&#xff08;層疊樣式表&#xff0c;Cascading Style Sheets&#xff09;是一種樣式表語言&#xff0c;用于描述 HTML 或 XML 文檔的布局和外觀&#xff0c;它允許開發者將文檔的內容結構與樣式表現分離&#xff0c;通過定義一系列的樣式規則來控制網頁…

Jenkins 集成 SonarQube 代碼靜態檢查使用說明

環境準備 Jenkins 服務器 確保 Jenkins 已安裝并運行&#xff08;推薦 LTS 版本&#xff09;。安裝插件&#xff1a; SonarQube Scanner for Jenkins&#xff08;用于集成 SonarQube 掃描&#xff09;NodeJS Plugin&#xff08;可選&#xff0c;用于 JavaScript 項目&#xff0…

EasyRTC輕量級Webrtc音視頻通話SDK,助力帶屏IPC在嵌入式設備中的應用

一、市場背景 隨著人們生活水平的提高&#xff0c;對于家居安全和遠程監控的需求日益增長&#xff0c;帶屏IPCam不僅滿足了用戶實時查看監控畫面的需求&#xff0c;還提供了諸如雙向語音通話、智能報警等豐富的功能&#xff0c;極大地提升了用戶體驗。 此外&#xff0c;技術的…

AI編輯器-Trae 玩轉AI 編程

參考 掘金社區地址 Trae下載地址 管理插件 Trae 從入門到實踐:AI 編碼的妙筆生花 掘金社區 掘金社區簡介 掘金是面向全球中文開發者的技術內容分享與交流平臺。我們通過技術文章、沸點、課程、直播等產品和服務,打造一個激發開發者創作靈感,激勵開發者沉淀分享,陪伴開發者…

C語言代碼如何操作硬件?

在嵌入式開發中&#xff0c;C代碼通過直接操作硬件寄存器來控制硬件&#xff0c;這些寄存器被映射到特定的內存地址。以下是其工作原理的詳細分步解釋&#xff1a; 1. 內存映射硬件寄存器 微控制器將外設&#xff08;如GPIO、定時器、UART等&#xff09;的寄存器映射到內存地…

Flume-試題

以下是對話中涉及的題目及其簡要解析&#xff1a; 1. 哪個 Flume Source 可用于監控某個端口&#xff0c;將流經端口的每一個文本行數據作為 Event 輸入&#xff1f; - A. Avro Source - B. exec Source - C. Spooling Directory Source - D. Netcat Source 2. 哪…

C++《紅黑樹》

在之前的篇章當中我們已經了解了基于二叉搜索樹的AVL樹&#xff0c;那么接下來在本篇當中將繼續來學習另一種基于二叉搜索樹的樹狀結構——紅黑樹&#xff0c;在此和之前學習AVL樹類似還是通過先了解紅黑樹是什么以及紅黑樹的結構特點&#xff0c;接下來在試著實現紅黑樹的結構…

【第23節】windows網絡編程模型(WSAEventSelect模型)

目錄 引言 一、WSAEventSelect模型概述 二、 WSAEventSelect模型的實現流程 2.1 創建一個事件對象&#xff0c;注冊網絡事件 2.2 等待網絡事件發生 2.3 獲取網絡事件 2.4 手動設置信號量和釋放資源 三、 WSAEventSelect模型偽代碼示例 四、完整實踐示例代碼 引言 在網…

概率預測之NGBoost(Natural Gradient Boosting)回歸和分位數(Quantile Regression)回歸

概率預測之NGBoost(Natural Gradient Boosting)回歸和線性分位數回歸 NGBoostNGBoost超參數解釋NGBoost.fitscore(X, Y)staged_predict(X)feature_importances_pred_dist 方法來獲取概率分布對象分位數回歸(Quantile Regression)smf.quantreg 對多變量數據進行分位數回歸分…

手撕算法——鏈表

算法基礎——鏈表-CSDN博客 一、排隊順序 題?來源&#xff1a;洛? 題?鏈接&#xff1a;B3630 排隊順序 - 洛谷 難度系數&#xff1a;★ 1. 題目描述 2. 算法原理 本題相當于告訴了我們每?個點的后繼&#xff0c;使?靜態鏈表的存儲?式能夠很好的還原這個隊列。 數組中 [1,…

RAG優化:python從零實現[吃一塹長一智]循環反饋Feedback

本文將介紹一種有反饋循環機制的RAG系統,讓當AI學會"吃一塹長一智",給傳統RAG裝了個"后悔"系統,讓AI能記住哪些回答被用戶點贊/拍磚,從此告別金魚記憶: 每次回答都像在玩roguelike:失敗結局會強化下次冒險悄悄把優質問答變成新知識卡牌,實現"以…

kotlin init執行順序

一 代碼 kotlin: package test.fclass Test1 { }class TestInit(s: String, i: Int) {var name: String? nullvar age 0private var a :Int 1init {this.name sthis.age iprintln("init代碼塊: $name, $age")}}轉成java // Test1.java package test.f;import…

使用cursor開發java案例——springboot整合elasticsearch

安裝elasticsearch 打開cursor&#xff0c;輸入如下提示詞 使用springboot整合elasticsearch。其中elasticsearch服務器ip&#xff1a;192.168.236.134 管理員用戶名elastic 管理員密碼 PdQy_xfR2yLhpok*MK_ 監聽端口9200點Accept all 使用idea打開生成的項目 &#xff0…

Java Collection API增強功能系列之一 Arrays.asList()

在Java編程中&#xff0c;Arrays.asList() 是一個高頻使用卻又容易引發陷阱的工具方法。它能夠快速將數組轉換為列表&#xff0c;但其特殊行為常常讓開發者踩坑。本文將深入剖析該方法的本質特性&#xff0c;并揭示其使用時的注意事項。一、方法定義與基礎用法 1. 方法簽名 p…

vue3 項目的最新eslint9 + prettier 配置

注意&#xff1a;eslint目前升級到9版本了 在 ESLint v9 中&#xff0c;配置文件已經從 .eslintrc 遷移到了 eslint.config.js 配置的方式和之前的方式不太一樣了&#xff01;&#xff01;&#xff01;&#xff01; 詳見自己的語雀文檔&#xff1a;5、新版eslint9prettier 配…

基于FPGA的16QAM+幀同步系統verilog開發,包含testbench,高斯信道,誤碼統計,可設置SNR

目錄 1.算法仿真效果 2.算法涉及理論知識概要 2.1 16QAM調制解調原理 2.2 幀同步 3.Verilog核心程序 4.完整算法代碼文件獲得 1.算法仿真效果 vivado2019.2仿真結果如下&#xff08;完整代碼運行后無水印&#xff09;&#xff1a; 設置SNR12db 將FPGA數據導入到MATLAB顯…

[學成在線]06-視頻分片上傳

上傳視頻 需求分析 教學機構人員進入媒資管理列表查詢自己上傳的媒資文件。 點擊“媒資管理” 進入媒資管理列表頁面查詢本機構上傳的媒資文件。 教育機構用戶在"媒資管理"頁面中點擊 "上傳視頻" 按鈕。 點擊“上傳視頻”打開上傳頁面 選擇要上傳的文件…

Maven安裝與環境配置

首先我們先介紹一些關于Maven的知識&#xff0c;如果著急直接看下面的安裝教程。 目錄 Maven介紹 Maven模型 Maven倉庫 Maven安裝 下載 安裝步驟 Maven介紹 Apache Maven是一個項目管理和構建工具&#xff0c;它基于項目對象模型(Project Object Model , 簡稱: POM)的概念…