LeetCode 215:數組中的第K個最大元素 - 兩種高效解法詳解

文章目錄

    • 問題描述
    • 解法一:快速選擇算法(QuickSelect)
      • 算法思想
      • 算法步驟
      • Java實現
      • 復雜度分析
      • 算法特點
    • 解法二:最小堆(優先隊列)
      • 算法思想
      • 算法步驟
      • Java實現
      • 復雜度分析
      • 算法特點
    • 兩種解法比較
    • 測試示例
    • 總結

在算法面試中,查找數組中第K個最大元素是一個經典問題。LeetCode第215題要求我們在未排序的數組中找到第K大的元素。本文將介紹兩種高效的解決方案:快速選擇算法和堆(優先隊列)方法,幫助你全面掌握這道高頻面試題。

問題描述

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

請注意,你需要找的是數組排序后的第 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 ≤ nums.length

解法一:快速選擇算法(QuickSelect)

算法思想

快速選擇算法基于快速排序的分區思想,通過每次分區將數組分為兩部分,然后根據目標位置選擇繼續分區其中一側,從而在平均 O(n) 的時間復雜度內解決問題。

算法步驟

  1. 隨機選擇樞軸:為了避免最壞情況,隨機選擇一個元素作為樞軸
  2. 分區操作
    • 將大于樞軸的元素移到左側
    • 將小于等于樞軸的元素移到右側
  3. 比較樞軸位置
    • 如果樞軸位置正好是k-1,返回該元素
    • 如果位置大于k-1,在左半部分繼續查找
    • 如果位置小于k-1,在右半部分繼續查找

Java實現

import java.util.Random;class Solution {public int findKthLargest(int[] nums, int k) {int left = 0;int right = nums.length - 1;int targetIndex = k - 1; // 第k大元素在降序數組中的索引Random rand = new Random();while (left <= right) {// 隨機選擇樞軸并交換到末尾int pivotIndex = left + rand.nextInt(right - left + 1);swap(nums, pivotIndex, right);// 分區操作,返回樞軸最終位置int partitionIndex = partition(nums, left, right);if (partitionIndex == targetIndex) {return nums[partitionIndex];} else if (partitionIndex > targetIndex) {right = partitionIndex - 1;} else {left = partitionIndex + 1;}}return -1; // 理論上不會執行到這里}// 分區函數:將大于樞軸的元素移到左側private int partition(int[] nums, int left, int right) {int pivot = nums[right];int i = left;for (int j = left; j < right; j++) {if (nums[j] > pivot) {swap(nums, i, j);i++;}}swap(nums, i, right);return i;}private void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}

復雜度分析

  • 時間復雜度
    • 平均情況:O(n)
    • 最壞情況:O(n2)(但隨機樞軸有效避免最壞情況)
  • 空間復雜度:O(1)

算法特點

  1. 原地操作,不需要額外空間
  2. 平均性能優異
  3. 會修改原始數組

解法二:最小堆(優先隊列)

算法思想

使用最小堆維護數組中最大的k個元素。堆頂元素(最小值)即為第k大的元素。

算法步驟

  1. 初始化大小為k的最小堆
  2. 遍歷數組:
    • 當堆大小小于k時,直接添加元素
    • 當堆已滿且當前元素大于堆頂時,替換堆頂元素
  3. 遍歷結束后,堆頂元素即為結果

Java實現

import java.util.PriorityQueue;class Solution {public int findKthLargest(int[] nums, int k) {// 創建最小堆PriorityQueue<Integer> minHeap = new PriorityQueue<>();for (int num : nums) {if (minHeap.size() < k) {minHeap.offer(num);} else if (num > minHeap.peek()) {minHeap.poll();minHeap.offer(num);}}return minHeap.peek();}
}

復雜度分析

  • 時間復雜度:O(n log k)
  • 空間復雜度:O(k)

算法特點

  1. 不修改原始數組
  2. 適合處理流式數據
  3. 代碼簡潔易懂
  4. 時間復雜度穩定

兩種解法比較

特性快速選擇算法最小堆方法
時間復雜度平均 O(n),最壞 O(n2)O(n log k)
空間復雜度O(1)O(k)
是否修改數組
適用場景空間要求高,可修改數組流式數據,保持原數組不變
穩定性不穩定穩定

測試示例

public class Main {public static void main(String[] args) {Solution solution = new Solution();int[] nums1 = {3, 2, 1, 5, 6, 4};int k1 = 2;System.out.println("示例1: " + solution.findKthLargest(nums1, k1)); // 5int[] nums2 = {3, 2, 3, 1, 2, 4, 5, 5, 6};int k2 = 4;System.out.println("示例2: " + solution.findKthLargest(nums2, k2)); // 4int[] nums3 = {7, 6, 5, 4, 3, 2, 1};int k3 = 3;System.out.println("示例3: " + solution.findKthLargest(nums3, k3)); // 5}
}

總結

LeetCode 215題"數組中的第K個最大元素"有兩種高效解法:

  1. 快速選擇算法

    • 優點:平均時間復雜度O(n),空間復雜度O(1)
    • 缺點:最壞情況O(n2),修改原數組
    • 適用場景:空間要求高,可接受修改數組
  2. 最小堆方法

    • 優點:時間復雜度穩定O(n log k),不修改原數組
    • 缺點:空間復雜度O(k)
    • 適用場景:流式數據,需要保持原數組不變

根據具體問題場景選擇合適的解法:

  • 對于內存敏感的場景,優先選擇快速選擇算法
  • 對于需要保持原數組或處理流式數據的場景,選擇最小堆方法

掌握這兩種解法及其適用場景,可以幫助你在面試中靈活應對不同變種問題。

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

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

相關文章

視頻壓制(Video Encoding/Compression)

視頻壓制是指通過特定的算法和技術&#xff0c;將原始視頻文件轉換為更小體積或更適合傳播的格式的過程。其核心目的是在盡量保持畫質的前提下&#xff0c;減少視頻的文件大小&#xff0c;或適配不同播放設備、網絡環境的需求。 --- ### **關鍵概念解析** 1. **為什么需要壓制…

如何做好一個決策:基于 Excel的決策樹+敏感性分析應用

決策點: 開發新產品? (是 / 否) 因素 (如果是): 市場接受度 (高 / 中 / 低);概率: 高(0.3), 中(0.5), 低(0.2) 結果值 (NPV): 高(+$1M), 中(+$0.2M), 低(-$0.5M) 不開發成本/收益: $0 開發計算: EMV(市場接受度) = (0.3 * 1M) + (0.5 * 0.2M) + (0.2 * -0.5M) = $0.3M + $…

Java中的設計模式實戰:單例、工廠、策略模式的最佳實踐

Java中的設計模式實戰&#xff1a;單例、工廠、策略模式的最佳實踐 在Java開發中&#xff0c;設計模式是構建高效、可維護、可擴展應用程序的關鍵。本文將深入探討三種常見且實用的設計模式&#xff1a;單例模式、工廠模式和策略模式&#xff0c;并通過詳細代碼實例&#xff0…

PyTorch學習(1):張量(Tensor)核心操作詳解

PyTorch學習(1)&#xff1a;張量&#xff08;Tensor&#xff09;核心操作詳解 一、張量&#xff08;Tensor&#xff09;核心操作詳解 張量是PyTorch的基礎數據結構&#xff0c;類似于NumPy的ndarray&#xff0c;但支持GPU加速和自動微分。 1. 張量創建與基礎屬性 import to…

Docker部署Spark大數據組件:配置log4j日志

上一篇《Docker部署Spark大數據組件》中&#xff0c;日志是輸出到console的&#xff0c;如果有將日志輸出到文件的需要&#xff0c;需要進一步配置。 配置將日志同時輸出到console和file 1、停止spark集群 docker-compose down -v 2、使用自帶log4j日志配置模板配置 cp -f …

Nginx Lua模塊(OpenResty)實戰:動態化、智能化你的Nginx,實現復雜Web邏輯 (2025)

更多服務器知識&#xff0c;盡在hostol.com 嘿&#xff0c;各位Nginx的“鐵桿粉絲”和“配置大師”們&#xff01;咱們都知道&#xff0c;Nginx以其超凡的性能、穩定性和豐富的模塊化功能&#xff0c;在Web服務器、反向代理、負載均衡等領域獨步青云&#xff0c;簡直是服務器軟…

一、CentOS7通過kubeadm安裝K8S 1.20.1版本

一、準備機器 所有節點執行 準備3臺虛擬機&#xff08;2核4G&#xff0c;CentOS 7&#xff09;&#xff0c;配置如下&#xff1a; hostnamectl set-hostname k8s-master # 在Master節點執行 hostnamectl set-hostname k8s-node1 # Worker1節點執行 hostnamectl set-hostna…

AgenticSeek,開源本地通用AI Agent,自主執行任務

AgenticSeek是一款完全本地化的開源AI助手&#xff0c;作為Manus的開源替代品&#xff0c;專為保護用戶隱私而設計。它能夠在本地設備上執行多種任務&#xff0c;包括網頁瀏覽、代碼編寫和復雜項目的規劃&#xff0c;確保所有操作和數據均在用戶的設備上完成。 AgenticSeek是什…

C 語言學習筆記(指針6)

內容提要 內存操作 內存操作的函數 內存操作 我們對于內存操作需要依賴于string.h頭文件中相關的庫函數。 內存的庫函數 內存填充 頭文件&#xff1a;#include <string.h>函數原型 void* memset(void* s, int c, size_t)函數功能&#xff1a;將內存塊s的前n個字節…

Grafana-Gauge儀表盤

儀表盤是一種單值可視化。 可讓您快速直觀地查看某個值落在定義的或計算出的最小和最大范圍內的位置。 通過重復選項&#xff0c;您可以顯示多個儀表盤&#xff0c;每個對應不同的序列、列或行。 支持的數據格式 單值 數據集中只有一個值&#xff0c;會生成一個顯示數值的…

解決Vue項目依賴錯誤:使用electron-vite重建

文章目錄 開端解決方案&#xff1a;使用 electron-vite Vue 重建項目1. 環境準備2. 創建新項目3. 安裝依賴并啟動項目 開端 在開發過程中&#xff0c;我遇到了一個令人頭疼的錯誤提示&#xff1a; 0:0 error Parsing error: Cannot find module vue/cli-plugin-babel/preset…

WPF prism

Prism Prism.Dryloc 包 安裝 Nuget 包 - Prism.DryIoc 1. 修改 App.xaml 修改 App.xaml 文件&#xff0c;添加 prism 命名空間, 繼承由 Application → PrismApplication&#xff0c;刪除默認啟動 url, StartupUri“MainWindow.xaml” <dryioc:PrismApplicationx:Class…

循序漸進PersistentVolumes與PersistentVolumeClaim

文章目錄 靜態配置&#xff08;Static Provisioning&#xff09;&#xff1a;Persistent volume(PV)Local 示例&#xff1a;NFS 示例&#xff1a;檢查pvPV 的常見狀態說明Persistent volume claim(PVC)1. local PVC示例:2.NFS PVC示例:3. 檢查PVC: 掛載靜態供應卷驗證靜態供應卷…

【連接器專題】SD卡座規格書審查需要審哪些方面?

在審查SD卡座規格書時,我們需要考慮哪些方面? 首先在拿到一份SD卡座的詳細規格書時,一般供應商給到的規格書中包括了一些基礎信息、產品圖紙信息、技術參數信息,同時有些供應商會給出產品可靠性測試報告。因此我們會從這幾個要素去看規格書。 基礎信息 基礎信息一般會給變更…

投稿 IEEE Transactions on Knowledge and Data Engineering 注意事項

投稿 IEEE Transactions on Knowledge and Data Engineering 注意事項 要IEEE overleaf 模板私信,我直接給我自己論文,便于編輯 已經投稿完成了,有一些小坑 準備工作 注冊IEEE賬戶:若沒有IEEE賬戶,需前往IEEE官網注冊。注冊成功后,可用于登錄投稿系統。現在新的系統,…

JS入門——三種輸入方式

JS入門——三種輸入方式 一、方式一&#xff1a;直接在警告框彈出(window可以省略) <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><script><!-- 方式一直接在警告框彈…

WordPress免費網站模板下載

大背景圖免費wordpress建站模板 這個wordpress模板設計以簡約和專業為主題&#xff0c;旨在為用戶提供清晰、直觀的瀏覽體驗。以下是對其風格、布局和設計理念的詳細介紹&#xff1a; 風格 簡約現代&#xff1a;整體設計采用簡約風格&#xff0c;使用了大量的白色和灰色調&am…

AUTOSAR CP全新系統化培訓上線!從底層到應用,三步階梯,五大學習維度構建完整知識體系

AUTOSAR組織 AUTOSAR官方全新推出「AUTOSAR CP全棧賦能計劃」&#xff0c;從架構全景到模塊細節&#xff0c;自底向上、由淺入深&#xff0c;覆蓋MCAL至SWC全層級&#xff0c;融合通信、診斷、安全等六大核心Feature&#xff0c;帶您穿透復雜理論&#xff0c;直擊AUTOSAR開發本…

Java網絡編程與Socket安全權限詳解

Socket安全權限控制 Java通過java.net.SocketPermission類實現對網絡套接字訪問的細粒度控制。該權限管理機制通常在Java策略文件中配置,其標準授權語法格式如下: grant {permission java.net.SocketPermission"target", "actions"; };目標主機與端口規…

基于本地化大模型的智能編程助手全棧實踐:從模型部署到IDE深度集成學習心得

近年來&#xff0c;隨著ChatGPT、Copilot等AI編程工具的爆發式增長&#xff0c;開發者生產力獲得了前所未有的提升。然而&#xff0c;云服務的延遲、隱私顧慮及API調用成本促使我探索一種更自主可控的方案&#xff1a;基于開源大模型構建本地化智能編程助手。本文將分享我構建本…