LeetCode 004. 尋找兩個正序數組的中位數 - 二分切分與分治詳解

一、文章標題

LeetCode 004. 尋找兩個正序數組的中位數 - 二分切分與分治詳解

二、文章內容

1. 題目概述
  • 題目描述:給定兩個已按非降序排列的整數數組 nums1、nums2,設它們長度分別為 m 和 n,要求返回這兩個數組合并后有序序列的中位數。整體期望時間復雜度為 O(log(m+n))。當總長度為偶數時,中位數為中間兩個數的平均值(返回 double)。數組可能為空,但不會同時為空(若實現中遇到同時為空需返回默認值)。
  • 原題鏈接:https://leetcode.cn/problems/median-of-two-sorted-arrays/
  • 難度等級:Hard
  • 相關標簽:數組、二分查找、分治、雙指針
2. 文章目錄

目錄

  1. 題目概述
  2. 解題思路
  3. 算法詳解
    • 3.1 解法一:雙指針線性掃描到中位數
    • 3.2 解法二:二分切分(最優)
  4. 解法對比
  5. 最優解推薦
3. 解題思路
  • 問題分析:
    • 輸入:兩個已排序的整型數組 nums1、nums2。
    • 輸出:合并后序列的中位數(double)。
    • 中位數定義:
      • 若 m+n 為奇數,中位數為第 (m+n)/2(0 基)處的元素。
      • 若 m+n 為偶數,中位數為第 (m+n)/2 - 1 與 (m+n)/2 兩個元素均值。
  • 核心難點:
    • 在不真正合并數組的前提下,以 O(log(m+n)) 時間找到中位數。
    • 復雜邊界處理:空數組、分割端點在數組兩側、奇偶長度處理、整型轉 double。
  • 解題方向:
    1. 線性合并/掃描到中位數位置(O(m+n),實現直觀,作為兜底)。
    2. 分治/找第 k 小(每輪丟棄 k/2 個元素,O(log(m+n)))。
    3. 二分切分(只對較短數組二分,構造左右兩半滿足有序關系,O(log(min(m,n))),最優)。
4. 算法詳解

解法一:雙指針線性掃描到中位數

算法原理

  • 核心思想:像歸并排序的合并過程一樣,用兩根指針從頭掃描兩個有序數組,不必真的合并,只需走到中位數所在下標就停止。
  • 適用場景:當不強求 O(log(m+n))、或用作對拍與兜底實現時非常好用。

具體實現

  • 步驟1:準備兩個指針 i、j 指向 nums1、nums2 開始位置,準備計數 idx 表示當前合并到的下標。
  • 步驟2:每次取兩個指針中較小的元素作為“當前值”,并向前推進對應指針,直到走到右側中位數下標 mid2。
  • 步驟3:根據總長度奇偶,返回 curr 或 (prev+curr)/2.0。

復雜度分析

  • 時間復雜度:O(m+n),最壞需要掃描完所有元素。
  • 空間復雜度:O(1),只用到常數額外變量。

Java代碼實現

class Solution {/*** 線性掃描到中位數位置的解法(O(m+n))。* 注意:為講解清晰,方法名與最優解區分;在 LeetCode 提交時可將最優解方法名改為題目要求的方法名。*/public double findMedianSortedArraysLinear(int[] nums1, int[] nums2) {// 將 null 視作空數組,避免空指針if (nums1 == null) nums1 = new int[0];if (nums2 == null) nums2 = new int[0];int m = nums1.length, n = nums2.length;int total = m + n;// 題目一般保證不會同時為空;為健壯性,這里返回默認值 0.0if (total == 0) {return 0.0;}// 左、右中位數的目標下標(0 基)int mid1 = (total - 1) / 2; // 左中位數int mid2 = total / 2;       // 右中位數int i = 0, j = 0;  // 兩個數組的掃描指針int idx = -1;      // 已經“取出”的元素個數 - 1int prev = 0;      // 上一個取出的值(用于偶數總長度)int curr = 0;      // 當前取出的值// 掃描直到到達右中位數位置while (idx < mid2) {prev = curr; // 記錄上一個值// 取較小值推進(當某一數組用盡時,取另一數組)if (i < m && (j >= n || nums1[i] <= nums2[j])) {curr = nums1[i++];} else if (j < n) {curr = nums2[j++];}idx++;}// 奇偶分別處理if ((total & 1) == 1) {return curr; // 奇數長度,中位數就是當前值} else {return (prev + curr) / 2.0; // 偶數長度,取均值}}
}

解法二:二分切分(最優)

算法原理

  • 基本思想:只對較短的數組進行二分,在兩個數組上找到一個“切分點對” (i, j),使得:
    • 左半部分長度等于右半部分長度(或只多 1),即 i + j = (m + n + 1) / 2;
    • 左半最大值 ≤ 右半最小值,即 max(A[i-1], B[j-1]) ≤ min(A[i], B[j])。
  • 一旦上述條件成立:
    • 若總長度為奇數,中位數是左半最大值;
    • 若為偶數,中位數是左半最大值與右半最小值的平均。
  • 適用場景:追求最優時間復雜度,面試高頻且邊界清晰的標準解。

具體實現

  • 步驟1:確保對更短的數組二分,令 A 為短數組,B 為長數組。
  • 步驟2:在 A 的 [0…m] 區間二分 i,令 j = (m+n+1)/2 - i。
  • 步驟3:檢查是否滿足分割條件;若 A[i-1] > B[j],說明 i 偏大,收縮右邊;若 B[j-1] > A[i],說明 i 偏小,收縮左邊;否則命中答案。

復雜度分析

  • 時間復雜度:O(log(min(m,n))),只在短數組長度范圍內二分。
  • 空間復雜度:O(1),常數額外空間。

Java代碼實現

class Solution {/*** 最優解:二分切分,時間復雜度 O(log(min(m,n))),空間 O(1)。* 若兩個數組都為空則返回 0.0 作為默認值,避免拋異常。*/public double findMedianSortedArrays(int[] nums1, int[] nums2) {// 將 null 視作空數組,避免空指針if (nums1 == null) nums1 = new int[0];if (nums2 == null) nums2 = new int[0];// 始終讓 A 為較短數組,B 為較長數組int[] A = nums1.length <= nums2.length ? nums1 : nums2;int[] B = (A == nums1) ? nums2 : nums1;int m = A.length, n = B.length;// 邊界:兩個都為空,返回默認值if (m + n == 0) {return 0.0;}int left = 0, right = m; // 在 A 的切分位置范圍 [0..m] 上二分int half = (m + n + 1) / 2; // 左半部分應包含的元素個數while (left <= right) {int i = left + (right - left) / 2; // A 的切分點int j = half - i;                  // B 的切分點,使得左半長度滿足要求// 處理邊界元素,越界時使用極小/極大的“哨兵”思想(用比較邏輯避免實際越界)int Aleft  = (i == 0) ? Integer.MIN_VALUE : A[i - 1];int Aright = (i == m) ? Integer.MAX_VALUE : A[i];int Bleft  = (j == 0) ? Integer.MIN_VALUE : B[j - 1];int Bright = (j == n) ? Integer.MAX_VALUE : B[j];// 檢查是否滿足切分正確:左邊最大 <= 右邊最小if (Aleft <= Bright && Bleft <= Aright) {// 命中:根據奇偶直接計算中位數if (((m + n) & 1) == 1) {// 奇數:中位數是左邊最大值int leftMax = Math.max(Aleft, Bleft);return (double) leftMax;} else {// 偶數:中位數是 左邊最大 與 右邊最小 的均值int leftMax = Math.max(Aleft, Bleft);int rightMin = Math.min(Aright, Bright);return (leftMax + rightMin) / 2.0;}} else if (Aleft > Bright) {// A 的左邊太大,i 需要左移right = i - 1;} else {// Bleft > Aright,i 需要右移left = i + 1;}}// 理論上一定能在循環內返回;為健壯性返回默認值return 0.0;}
}
5. 解法對比與總結
解法時間復雜度空間復雜度優點缺點適用場景
雙指針線性掃描到中位數O(m+n)O(1)實現直觀、邊界簡單、易調試不滿足題目要求的對數級時間數據量不大、或作為兜底與對拍
二分切分(最優)O(log(min(m,n)))O(1)滿足最優時間、無需額外空間、思路標準邊界處理細節較多,上手需練習面試高頻、追求最優性能

最優解推薦:二分切分。其時間復雜度 O(log(min(m,n))),空間 O(1),能嚴格滿足題目對數級要求,且是工業界與面試中的標準寫法,值得熟練掌握。

三、文章標簽

算法,二分查找,LeetCode,困難,數組,雙指針,分治

四、文章簡述

本題考察兩個有序數組的中位數,給出線性雙指針與二分切分兩種方案。重點講解邊界處理、奇偶長度與復雜度分析,附帶完整 Java 實現與注釋,含對比與選型建議,適合面試與算法進階讀者。

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

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

相關文章

預閃為什么可以用來防紅眼?

打閃拍照紅眼產生的原因 預閃可以用來防紅眼&#xff0c;是基于人眼的生理特性和紅眼現象的產生原理。在光線較暗時&#xff0c;人眼的瞳孔會放大。當使用閃光燈拍攝時&#xff0c;如果直接進行高強度閃光&#xff0c;由于瞳孔來不及縮小&#xff0c;閃光燈的光線會反射在眼球血…

Python程序使用了Ffmpeg,結束程序后,文件夾中仍然生成音頻、視頻文件

FFmpeg是一套可以用來記錄、轉換數字音頻、視頻&#xff0c;并能將其轉化為流的開源計算機程序。采用LGPL或GPL許可證。它提供了錄制、轉換以及流化音視頻的完整解決方案。它包含了非常先進的音頻/視頻編解碼庫libavcodec&#xff0c;為了保證高可移植性和編解碼質量&#xff0…

模塊與包的導入

077-模塊-06-模塊搜索順序_嗶哩嗶哩_bilibili 080-包-01-包的概念以及建立包的方式_嗶哩嗶哩_bilibili 088-文件操作-01-文件操作套路以及Python中的對應函數和方法_嗶哩嗶哩_bilibili 注&#xff1a; 1.import math和 from math import *區別 2. 模塊&#xff08;Module…

Docker Compose 多種安裝方式 (Alibaba Cloud Linux 3 環境)

Docker Compose 多種安裝方式&#xff0c;適用于不同場景&#xff08;如依賴系統包管理器、使用 Python 工具鏈、集成 Docker 插件等&#xff09;。以下是常見的方案&#xff0c;尤其針對 Alibaba Cloud Linux 3 環境適配&#xff1a; 一、二進制包安裝&#xff08;推薦&#…

Dubbo3序列化安全機制導致的一次生產故障

前言 記錄一次 Dubbo 線上故障排查和原因分析。 線上 Dubbo 消費者啟動有錯誤日志如下&#xff0c;但是不影響服務啟動。 java.lang.TypeNotPresentException: Type org.example.model.ThirdParam not present ... Caused by: java.lang.ClassNotFoundException: org.example.m…

centos7 docker離線安裝

介紹 本文主要講了如何在完全沒網的情況下安裝docker&#xff08;適合于高網絡安全要求的企業&#xff09; 本文適用的centos版本&#xff1a; [root0001 temp]# cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) 采用docker in docker下載依賴 實際試驗后&…

東京本社招聘 | 財務負責人 多個日本IT崗位(Java/C++/Python/AWS 等),IT營業同步招募

大家好&#xff0c;本期為大家帶來我司在東京GSD本社及其他會社千葉地區的招聘崗位。 涵蓋 財務負責人、Java開發工程師、數據中心維護工程師、項目經理、IT營業 等多個職位。 歡迎有志之士加入&#xff01;&#x1f539; 財務負責人&#xff08;東京本社&#xff09;工作內容日…

四數之和

目錄 一&#xff1a;題目鏈接 二&#xff1a;題目思路 三&#xff1a;代碼實現 一&#xff1a;題目鏈接 理解題目需要注意&#xff0c;如果兩個四元組元素一一對應&#xff0c;則認為兩個四元組重復&#xff0c;選擇其中一個四元組即可。比如 [ 0 , 1 , 0 , 2] 和 [ 1 , …

【序列晉升】29 Spring Cloud Task 微服務架構下的輕量級任務調度框架

Spring Cloud Task作為微服務架構中的輕量級任務調度框架&#xff0c;為開發人員提供了一種構建短生命周期微服務任務的便捷方式。它允許開發者快速創建、執行和管理一次性任務或短期批處理作業&#xff0c;任務執行完成后自動關閉以釋放系統資源&#xff0c;避免了傳統長期運行…

【1分鐘速通】 HTML快速入門

HTML&#xff08;HyperText Markup Language&#xff0c;超文本標記語言&#xff09; 是構建網頁的基礎語言。它通過 標簽&#xff08;Tag&#xff09; 來描述網頁的結構和內容&#xff0c;常與 CSS&#xff08;負責樣式 – <style></style>&#xff09;和 JavaScr…

【GeoServer】WMS GetFeatureInfo URL 逐個參數解釋

我來把你構造的這個 WMS GetFeatureInfo URL 逐個參數解釋一下&#xff0c;方便你理解&#xff1a;http://127.0.0.1:8090/geoserver/xxxx/wms? SERVICEWMS& VERSION1.1.1& REQUESTGetFeatureInfo& QUERY_LAYERSloess:yourLayer& LAYERSloess:yourLayer& …

OBS直播教程:點歌直播間怎么弄?直播點歌用什么軟件?

OBS直播教程&#xff1a;點歌直播間怎么弄&#xff1f;直播點歌用什么軟件&#xff1f; 第一步&#xff1a;安裝OBS直播軟件&#xff0c;如果你電腦已經安裝了OBS&#xff0c;請直接看第二步 OBS直播軟件下載地址①&#xff1a; https://d.obscj.com/obs-Studio-29.1.3-Full-…

【數據庫】Redis詳解:內存數據庫與緩存之王

什么是Redis&#xff1f; Redis&#xff08;Remote Dictionary Server&#xff09;是一個開源的、基于內存的數據結構存儲系統&#xff0c;可以用作數據庫、緩存和消息代理。它支持多種數據結構&#xff0c;如字符串、哈希、列表、集合、有序集合等&#xff0c;具有極高的性能和…

【iOS】 單例模式

1. 認識單例模式首先讓我們先看下關于單例模式的定義&#xff08;來自于《設計模式》(Addison-Wesley,1994)&#xff09;一個類有且僅有一個實例&#xff0c;并且自行實例化向整個系統提供。如果說每一個人都是一個類&#xff0c;那么從他出生開始&#xff0c;他就是生活中的唯…

多目標輪廓匹配

前面我們使用模板匹配&#xff0c;得到的結果都是一個圖&#xff0c;那么如果我們圖片中有許多我們的目標&#xff0c;那么該如何找出來呢&#xff1f;如上我們圖片中有許多箭頭和我們的模板一致&#xff0c;只不過方向不對&#xff0c;那么該如何匹配呢&#xff1f;圖片和模板…

【C++】簡單介紹lambda表達式

各位大佬好&#xff0c;我是落羽&#xff01;一個堅持不斷學習進步的學生。 如果您覺得我的文章還不錯&#xff0c;歡迎多多互三分享交流&#xff0c;一起學習進步&#xff01; 也歡迎關注我的blog主頁: 落羽的落羽 文章目錄一、 什么是lambda表達式二、 表達式語法三、lambd…

磁共振成像原理(理論)4:自由進動和弛豫 (Free Precession and Relaxation)

當磁化自旋系統被射頻脈沖擾動而偏離其熱平衡態后&#xff0c;一旦移除外部激勵并給予足夠時間&#xff0c;系統將根據熱力學定律返回平衡態。這一過程包含三個特征現象&#xff1a; (a) 自由進動——宏觀磁化矢量 (M?\vec{M}M) 繞( B0?\vec {B_0}B0?? )場的進動&#xff1…

ubuntu 20.04 安裝spark

安裝openjdk21 下載 wget https://download.java.net/openjdk/jdk21/ri/openjdk-2135_linux-x64_bin.tar.gz解壓 tar -xvf openjdk-2135_linux-x64_bin.tar.gzsudo mv jdk-21/ /opt/jdk-21/設置環境變量 echo export JAVA_HOME/opt/jdk-21 | sudo tee /etc/profile.d/java2…

第三方區塊鏈應用測評:【多簽錢包合約安全評估_閾值簽名機制與私鑰存儲安全性測試】

閾值簽名機制安全測試密碼學審計 采用門限簽名方案&#xff08;TSS&#xff09;的多簽錢包需驗證其閾值BLS簽名或ECDSA簽名算法的正確性。測試重點包括&#xff1a;分布式密鑰生成&#xff08;DKG&#xff09;過程的保密性&#xff08;無密鑰信息泄露&#xff09;、簽名碎片驗證…

大模型處理長文檔的挑戰和解決方案?

當前&#xff0c;AI 應用正處于極速發展階段&#xff0c;大語言模型&#xff08;LLM&#xff09;與檢索增強生成&#xff08;RAG&#xff09;系統已成為構建智能問答、知識管理等高階 AI 應用的核心引擎&#xff0c;被廣泛應用于金融分析、學術研究、企業合規等多個領域。然而&…